From 7177786a432a86b28ec74d41eafce70dba8a54a3 Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Fri, 10 Jun 2016 22:32:00 -0500 Subject: [PATCH 01/34] Start React version --- __html/.bowerrc | 3 + __html/.editorconfig | 21 + __html/.gitattributes | 1 + __html/.gitignore | 6 + __html/.jshintrc | 23 ++ __html/.travis.yml | 6 + __html/Gruntfile.js | 441 ++++++++++++++++++++ __html/Makefile | 6 + __html/app/.buildignore | 1 + __html/app/.htaccess | 543 +++++++++++++++++++++++++ __html/app/favicon.ico | Bin 0 -> 6782 bytes __html/app/images/logo.svg | 50 +++ __html/app/index.html | 118 ++++++ __html/app/scripts/app.js | 49 +++ __html/app/scripts/controllers/main.js | 142 +++++++ __html/app/scripts/services/main.js | 62 +++ __html/app/styles/main.scss | 197 +++++++++ __html/app/views/details.html | 70 ++++ __html/app/views/main.html | 108 +++++ __html/bower.json | 22 + __html/package.json | 44 ++ __html/test/.jshintrc | 36 ++ __html/test/karma.conf.js | 75 ++++ __html/test/spec/controllers/about.js | 22 + __html/test/spec/controllers/main.js | 22 + 25 files changed, 2068 insertions(+) create mode 100644 __html/.bowerrc create mode 100644 __html/.editorconfig create mode 100644 __html/.gitattributes create mode 100644 __html/.gitignore create mode 100644 __html/.jshintrc create mode 100644 __html/.travis.yml create mode 100644 __html/Gruntfile.js create mode 100644 __html/Makefile create mode 100644 __html/app/.buildignore create mode 100644 __html/app/.htaccess create mode 100644 __html/app/favicon.ico create mode 100644 __html/app/images/logo.svg create mode 100644 __html/app/index.html create mode 100644 __html/app/scripts/app.js create mode 100644 __html/app/scripts/controllers/main.js create mode 100644 __html/app/scripts/services/main.js create mode 100644 __html/app/styles/main.scss create mode 100644 __html/app/views/details.html create mode 100644 __html/app/views/main.html create mode 100644 __html/bower.json create mode 100644 __html/package.json create mode 100644 __html/test/.jshintrc create mode 100644 __html/test/karma.conf.js create mode 100644 __html/test/spec/controllers/about.js create mode 100644 __html/test/spec/controllers/main.js diff --git a/__html/.bowerrc b/__html/.bowerrc new file mode 100644 index 0000000..69fad35 --- /dev/null +++ b/__html/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory": "bower_components" +} diff --git a/__html/.editorconfig b/__html/.editorconfig new file mode 100644 index 0000000..c2cdfb8 --- /dev/null +++ b/__html/.editorconfig @@ -0,0 +1,21 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + + +[*] + +# Change these settings to your own preference +indent_style = space +indent_size = 2 + +# We recommend you to keep these unchanged +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/__html/.gitattributes b/__html/.gitattributes new file mode 100644 index 0000000..2125666 --- /dev/null +++ b/__html/.gitattributes @@ -0,0 +1 @@ +* text=auto \ No newline at end of file diff --git a/__html/.gitignore b/__html/.gitignore new file mode 100644 index 0000000..980a1aa --- /dev/null +++ b/__html/.gitignore @@ -0,0 +1,6 @@ +node_modules +*.swp +dist +.tmp +.sass-cache +bower_components diff --git a/__html/.jshintrc b/__html/.jshintrc new file mode 100644 index 0000000..f750969 --- /dev/null +++ b/__html/.jshintrc @@ -0,0 +1,23 @@ +{ + "node": true, + "browser": true, + "esnext": true, + "bitwise": true, + "camelcase": true, + "curly": true, + "eqeqeq": true, + "immed": true, + "indent": 2, + "latedef": true, + "newcap": true, + "noarg": true, + "quotmark": "single", + "undef": true, + "unused": true, + "strict": true, + "trailing": true, + "smarttabs": true, + "globals": { + "angular": false + } +} diff --git a/__html/.travis.yml b/__html/.travis.yml new file mode 100644 index 0000000..a80b6e0 --- /dev/null +++ b/__html/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - '0.10' +before_script: + - 'npm install -g bower grunt-cli' + - 'bower install' diff --git a/__html/Gruntfile.js b/__html/Gruntfile.js new file mode 100644 index 0000000..737d49a --- /dev/null +++ b/__html/Gruntfile.js @@ -0,0 +1,441 @@ +// Generated on 2014-12-20 using generator-angular 0.10.0 +'use strict'; + +// # Globbing +// for performance reasons we're only matching one level down: +// 'test/spec/{,*/}*.js' +// use this if you want to recursively match all subfolders: +// 'test/spec/**/*.js' + +module.exports = function (grunt) { + + // Load grunt tasks automatically + require('load-grunt-tasks')(grunt); + + // Time how long tasks take. Can help when optimizing build times + require('time-grunt')(grunt); + + // Configurable paths for the application + var appConfig = { + app: require('./bower.json').appPath || 'app', + dist: 'dist' + }; + + // Define the configuration for all the tasks + grunt.initConfig({ + + // Project settings + yeoman: appConfig, + + // Watches files for changes and runs tasks based on the changed files + watch: { + bower: { + files: ['bower.json'], + tasks: ['wiredep'] + }, + js: { + files: ['<%= yeoman.app %>/scripts/{,*/}*.js'], + tasks: ['newer:jshint:all'], + options: { + livereload: '<%= connect.options.livereload %>' + } + }, + jsTest: { + files: ['test/spec/{,*/}*.js'], + tasks: ['newer:jshint:test', 'karma'] + }, + compass: { + files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'], + tasks: ['compass:server', 'autoprefixer'] + }, + gruntfile: { + files: ['Gruntfile.js'] + }, + livereload: { + options: { + livereload: '<%= connect.options.livereload %>' + }, + files: [ + '<%= yeoman.app %>/{,*/}*.html', + '.tmp/styles/{,*/}*.css', + '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}' + ] + } + }, + + // The actual grunt server settings + connect: { + options: { + port: 9000, + // Change this to '0.0.0.0' to access the server from outside. + hostname: 'localhost', + livereload: 35729 + }, + livereload: { + options: { + open: true, + middleware: function (connect) { + return [ + connect.static('.tmp'), + connect().use( + '/bower_components', + connect.static('./bower_components') + ), + connect.static(appConfig.app) + ]; + } + } + }, + test: { + options: { + port: 9001, + middleware: function (connect) { + return [ + connect.static('.tmp'), + connect.static('test'), + connect().use( + '/bower_components', + connect.static('./bower_components') + ), + connect.static(appConfig.app) + ]; + } + } + }, + dist: { + options: { + open: true, + base: '<%= yeoman.dist %>' + } + } + }, + + // Make sure code styles are up to par and there are no obvious mistakes + jshint: { + options: { + jshintrc: '.jshintrc', + reporter: require('jshint-stylish') + }, + all: { + src: [ + 'Gruntfile.js', + '<%= yeoman.app %>/scripts/{,*/}*.js' + ] + }, + test: { + options: { + jshintrc: 'test/.jshintrc' + }, + src: ['test/spec/{,*/}*.js'] + } + }, + + // Empties folders to start fresh + clean: { + dist: { + files: [{ + dot: true, + src: [ + '.tmp', + '<%= yeoman.dist %>/{,*/}*', + '!<%= yeoman.dist %>/.git{,*/}*' + ] + }] + }, + server: '.tmp' + }, + + // Add vendor prefixed styles + autoprefixer: { + options: { + browsers: ['last 1 version'] + }, + dist: { + files: [{ + expand: true, + cwd: '.tmp/styles/', + src: '{,*/}*.css', + dest: '.tmp/styles/' + }] + } + }, + + // Automatically inject Bower components into the app + wiredep: { + app: { + src: ['<%= yeoman.app %>/index.html'], + ignorePath: /\.\.\// + }, + sass: { + src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'], + ignorePath: /(\.\.\/){1,2}bower_components\// + } + }, + + // Compiles Sass to CSS and generates necessary files if requested + compass: { + options: { + sassDir: '<%= yeoman.app %>/styles', + cssDir: '.tmp/styles', + generatedImagesDir: '.tmp/images/generated', + imagesDir: '<%= yeoman.app %>/images', + javascriptsDir: '<%= yeoman.app %>/scripts', + fontsDir: '<%= yeoman.app %>/styles/fonts', + importPath: './bower_components', + httpImagesPath: '/images', + httpGeneratedImagesPath: '/images/generated', + httpFontsPath: '/styles/fonts', + relativeAssets: false, + assetCacheBuster: false, + raw: 'Sass::Script::Number.precision = 10\n' + }, + dist: { + options: { + generatedImagesDir: '<%= yeoman.dist %>/images/generated' + } + }, + server: { + options: { + debugInfo: true + } + } + }, + + // Renames files for browser caching purposes + filerev: { + dist: { + src: [ + '<%= yeoman.dist %>/scripts/{,*/}*.js', + '<%= yeoman.dist %>/styles/{,*/}*.css', + '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}', + '<%= yeoman.dist %>/styles/fonts/*' + ] + } + }, + + // Reads HTML for usemin blocks to enable smart builds that automatically + // concat, minify and revision files. Creates configurations in memory so + // additional tasks can operate on them + useminPrepare: { + html: '<%= yeoman.app %>/index.html', + options: { + dest: '<%= yeoman.dist %>', + flow: { + html: { + steps: { + js: ['concat', 'uglifyjs'], + css: ['cssmin'] + }, + post: {} + } + } + } + }, + + // Performs rewrites based on filerev and the useminPrepare configuration + usemin: { + html: ['<%= yeoman.dist %>/{,*/}*.html'], + css: ['<%= yeoman.dist %>/styles/{,*/}*.css'], + options: { + assetsDirs: ['<%= yeoman.dist %>','<%= yeoman.dist %>/images'] + } + }, + + // The following *-min tasks will produce minified files in the dist folder + // By default, your `index.html`'s will take care of + // minification. These next options are pre-configured if you do not wish + // to use the Usemin blocks. + // cssmin: { + // dist: { + // files: { + // '<%= yeoman.dist %>/styles/main.css': [ + // '.tmp/styles/{,*/}*.css' + // ] + // } + // } + // }, + // uglify: { + // dist: { + // files: { + // '<%= yeoman.dist %>/scripts/scripts.js': [ + // '<%= yeoman.dist %>/scripts/scripts.js' + // ] + // } + // } + // }, + // concat: { + // dist: {} + // }, + + imagemin: { + dist: { + files: [{ + expand: true, + cwd: '<%= yeoman.app %>/images', + src: '{,*/}*.{png,jpg,jpeg,gif}', + dest: '<%= yeoman.dist %>/images' + }] + } + }, + + svgmin: { + dist: { + files: [{ + expand: true, + cwd: '<%= yeoman.app %>/images', + src: '{,*/}*.svg', + dest: '<%= yeoman.dist %>/images' + }] + } + }, + + htmlmin: { + dist: { + options: { + collapseWhitespace: true, + conservativeCollapse: true, + collapseBooleanAttributes: true, + removeCommentsFromCDATA: true, + removeOptionalTags: true + }, + files: [{ + expand: true, + cwd: '<%= yeoman.dist %>', + src: ['*.html', 'views/{,*/}*.html'], + dest: '<%= yeoman.dist %>' + }] + } + }, + + // ng-annotate tries to make the code safe for minification automatically + // by using the Angular long form for dependency injection. + ngAnnotate: { + dist: { + files: [{ + expand: true, + cwd: '.tmp/concat/scripts', + src: ['*.js', '!oldieshim.js'], + dest: '.tmp/concat/scripts' + }] + } + }, + + // Replace Google CDN references + cdnify: { + dist: { + html: ['<%= yeoman.dist %>/*.html'] + } + }, + + // Copies remaining files to places other tasks can use + copy: { + dist: { + files: [{ + expand: true, + dot: true, + cwd: '<%= yeoman.app %>', + dest: '<%= yeoman.dist %>', + src: [ + '*.{ico,png,txt}', + '.htaccess', + '*.html', + 'views/{,*/}*.html', + 'images/{,*/}*.{webp}', + 'fonts/{,*/}*.*' + ] + }, { + expand: true, + cwd: '.tmp/images', + dest: '<%= yeoman.dist %>/images', + src: ['generated/*'] + }, { + expand: true, + cwd: '.', + src: 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*', + dest: '<%= yeoman.dist %>' + }] + }, + styles: { + expand: true, + cwd: '<%= yeoman.app %>/styles', + dest: '.tmp/styles/', + src: '{,*/}*.css' + } + }, + + // Run some tasks in parallel to speed up the build process + concurrent: { + server: [ + 'compass:server' + ], + test: [ + 'compass' + ], + dist: [ + 'compass:dist', + 'imagemin', + 'svgmin' + ] + }, + + // Test settings + karma: { + unit: { + configFile: 'test/karma.conf.js', + singleRun: true + } + } + }); + + + grunt.registerTask('serve', 'Compile then start a connect web server', function (target) { + if (target === 'dist') { + return grunt.task.run(['build', 'connect:dist:keepalive']); + } + + grunt.task.run([ + 'clean:server', + 'wiredep', + 'concurrent:server', + 'autoprefixer', + 'connect:livereload', + 'watch' + ]); + }); + + grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) { + grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.'); + grunt.task.run(['serve:' + target]); + }); + + grunt.registerTask('test', [ + 'clean:server', + 'concurrent:test', + 'autoprefixer', + 'connect:test', + 'karma' + ]); + + grunt.registerTask('build', [ + 'clean:dist', + 'wiredep', + 'useminPrepare', + 'concurrent:dist', + 'autoprefixer', + 'concat', + 'ngAnnotate', + 'copy:dist', + 'cdnify', + 'cssmin', + 'uglify', + 'filerev', + 'usemin', + 'htmlmin' + ]); + + grunt.registerTask('default', [ + 'newer:jshint', + 'test', + 'build' + ]); +}; diff --git a/__html/Makefile b/__html/Makefile new file mode 100644 index 0000000..64337a5 --- /dev/null +++ b/__html/Makefile @@ -0,0 +1,6 @@ +clean: + grunt clean + +publish: clean + grunt build + scp -r dist/* www-data@hyperfox.org:/var/www/hyperfox.org/live/ diff --git a/__html/app/.buildignore b/__html/app/.buildignore new file mode 100644 index 0000000..fc98b8e --- /dev/null +++ b/__html/app/.buildignore @@ -0,0 +1 @@ +*.coffee \ No newline at end of file diff --git a/__html/app/.htaccess b/__html/app/.htaccess new file mode 100644 index 0000000..cb84cb9 --- /dev/null +++ b/__html/app/.htaccess @@ -0,0 +1,543 @@ +# Apache Configuration File + +# (!) Using `.htaccess` files slows down Apache, therefore, if you have access +# to the main server config file (usually called `httpd.conf`), you should add +# this logic there: http://httpd.apache.org/docs/current/howto/htaccess.html. + +# ############################################################################## +# # CROSS-ORIGIN RESOURCE SHARING (CORS) # +# ############################################################################## + +# ------------------------------------------------------------------------------ +# | Cross-domain AJAX requests | +# ------------------------------------------------------------------------------ + +# Enable cross-origin AJAX requests. +# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity +# http://enable-cors.org/ + +# +# Header set Access-Control-Allow-Origin "*" +# + +# ------------------------------------------------------------------------------ +# | CORS-enabled images | +# ------------------------------------------------------------------------------ + +# Send the CORS header for images when browsers request it. +# https://developer.mozilla.org/en/CORS_Enabled_Image +# http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html +# http://hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/ + + + + + SetEnvIf Origin ":" IS_CORS + Header set Access-Control-Allow-Origin "*" env=IS_CORS + + + + +# ------------------------------------------------------------------------------ +# | Web fonts access | +# ------------------------------------------------------------------------------ + +# Allow access from all domains for web fonts + + + + Header set Access-Control-Allow-Origin "*" + + + + +# ############################################################################## +# # ERRORS # +# ############################################################################## + +# ------------------------------------------------------------------------------ +# | 404 error prevention for non-existing redirected folders | +# ------------------------------------------------------------------------------ + +# Prevent Apache from returning a 404 error for a rewrite if a directory +# with the same name does not exist. +# http://httpd.apache.org/docs/current/content-negotiation.html#multiviews +# http://www.webmasterworld.com/apache/3808792.htm + +Options -MultiViews + +# ------------------------------------------------------------------------------ +# | Custom error messages / pages | +# ------------------------------------------------------------------------------ + +# You can customize what Apache returns to the client in case of an error (see +# http://httpd.apache.org/docs/current/mod/core.html#errordocument), e.g.: + +ErrorDocument 404 /404.html + + +# ############################################################################## +# # INTERNET EXPLORER # +# ############################################################################## + +# ------------------------------------------------------------------------------ +# | Better website experience | +# ------------------------------------------------------------------------------ + +# Force IE to render pages in the highest available mode in the various +# cases when it may not: http://hsivonen.iki.fi/doctype/ie-mode.pdf. + + + Header set X-UA-Compatible "IE=edge" + # `mod_headers` can't match based on the content-type, however, we only + # want to send this header for HTML pages and not for the other resources + + Header unset X-UA-Compatible + + + +# ------------------------------------------------------------------------------ +# | Cookie setting from iframes | +# ------------------------------------------------------------------------------ + +# Allow cookies to be set from iframes in IE. + +# +# Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"" +# + +# ------------------------------------------------------------------------------ +# | Screen flicker | +# ------------------------------------------------------------------------------ + +# Stop screen flicker in IE on CSS rollovers (this only works in +# combination with the `ExpiresByType` directives for images from below). + +# BrowserMatch "MSIE" brokenvary=1 +# BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1 +# BrowserMatch "Opera" !brokenvary +# SetEnvIf brokenvary 1 force-no-vary + + +# ############################################################################## +# # MIME TYPES AND ENCODING # +# ############################################################################## + +# ------------------------------------------------------------------------------ +# | Proper MIME types for all files | +# ------------------------------------------------------------------------------ + + + + # Audio + AddType audio/mp4 m4a f4a f4b + AddType audio/ogg oga ogg + + # JavaScript + # Normalize to standard type (it's sniffed in IE anyways): + # http://tools.ietf.org/html/rfc4329#section-7.2 + AddType application/javascript js jsonp + AddType application/json json + + # Video + AddType video/mp4 mp4 m4v f4v f4p + AddType video/ogg ogv + AddType video/webm webm + AddType video/x-flv flv + + # Web fonts + AddType application/font-woff woff + AddType application/vnd.ms-fontobject eot + + # Browsers usually ignore the font MIME types and sniff the content, + # however, Chrome shows a warning if other MIME types are used for the + # following fonts. + AddType application/x-font-ttf ttc ttf + AddType font/opentype otf + + # Make SVGZ fonts work on iPad: + # https://twitter.com/FontSquirrel/status/14855840545 + AddType image/svg+xml svg svgz + AddEncoding gzip svgz + + # Other + AddType application/octet-stream safariextz + AddType application/x-chrome-extension crx + AddType application/x-opera-extension oex + AddType application/x-shockwave-flash swf + AddType application/x-web-app-manifest+json webapp + AddType application/x-xpinstall xpi + AddType application/xml atom rdf rss xml + AddType image/webp webp + AddType image/x-icon ico + AddType text/cache-manifest appcache manifest + AddType text/vtt vtt + AddType text/x-component htc + AddType text/x-vcard vcf + + + +# ------------------------------------------------------------------------------ +# | UTF-8 encoding | +# ------------------------------------------------------------------------------ + +# Use UTF-8 encoding for anything served as `text/html` or `text/plain`. +AddDefaultCharset utf-8 + +# Force UTF-8 for certain file formats. + + AddCharset utf-8 .atom .css .js .json .rss .vtt .webapp .xml + + + +# ############################################################################## +# # URL REWRITES # +# ############################################################################## + +# ------------------------------------------------------------------------------ +# | Rewrite engine | +# ------------------------------------------------------------------------------ + +# Turning on the rewrite engine and enabling the `FollowSymLinks` option is +# necessary for the following directives to work. + +# If your web host doesn't allow the `FollowSymlinks` option, you may need to +# comment it out and use `Options +SymLinksIfOwnerMatch` but, be aware of the +# performance impact: http://httpd.apache.org/docs/current/misc/perf-tuning.html#symlinks + +# Also, some cloud hosting services require `RewriteBase` to be set: +# http://www.rackspace.com/knowledge_center/frequently-asked-question/why-is-mod-rewrite-not-working-on-my-site + + + Options +FollowSymlinks + # Options +SymLinksIfOwnerMatch + RewriteEngine On + # RewriteBase / + + +# ------------------------------------------------------------------------------ +# | Suppressing / Forcing the "www." at the beginning of URLs | +# ------------------------------------------------------------------------------ + +# The same content should never be available under two different URLs especially +# not with and without "www." at the beginning. This can cause SEO problems +# (duplicate content), therefore, you should choose one of the alternatives and +# redirect the other one. + +# By default option 1 (no "www.") is activated: +# http://no-www.org/faq.php?q=class_b + +# If you'd prefer to use option 2, just comment out all the lines from option 1 +# and uncomment the ones from option 2. + +# IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME! + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +# Option 1: rewrite www.example.com → example.com + + + RewriteCond %{HTTPS} !=on + RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] + RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L] + + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +# Option 2: rewrite example.com → www.example.com + +# Be aware that the following might not be a good idea if you use "real" +# subdomains for certain parts of your website. + +# +# RewriteCond %{HTTPS} !=on +# RewriteCond %{HTTP_HOST} !^www\..+$ [NC] +# RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L] +# + + +# ############################################################################## +# # SECURITY # +# ############################################################################## + +# ------------------------------------------------------------------------------ +# | Content Security Policy (CSP) | +# ------------------------------------------------------------------------------ + +# You can mitigate the risk of cross-site scripting and other content-injection +# attacks by setting a Content Security Policy which whitelists trusted sources +# of content for your site. + +# The example header below allows ONLY scripts that are loaded from the current +# site's origin (no inline scripts, no CDN, etc). This almost certainly won't +# work as-is for your site! + +# To get all the details you'll need to craft a reasonable policy for your site, +# read: http://html5rocks.com/en/tutorials/security/content-security-policy (or +# see the specification: http://w3.org/TR/CSP). + +# +# Header set Content-Security-Policy "script-src 'self'; object-src 'self'" +# +# Header unset Content-Security-Policy +# +# + +# ------------------------------------------------------------------------------ +# | File access | +# ------------------------------------------------------------------------------ + +# Block access to directories without a default document. +# Usually you should leave this uncommented because you shouldn't allow anyone +# to surf through every directory on your server (which may includes rather +# private places like the CMS's directories). + + + Options -Indexes + + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +# Block access to hidden files and directories. +# This includes directories used by version control systems such as Git and SVN. + + + RewriteCond %{SCRIPT_FILENAME} -d [OR] + RewriteCond %{SCRIPT_FILENAME} -f + RewriteRule "(^|/)\." - [F] + + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +# Block access to backup and source files. +# These files may be left by some text editors and can pose a great security +# danger when anyone has access to them. + + + Order allow,deny + Deny from all + Satisfy All + + +# ------------------------------------------------------------------------------ +# | Secure Sockets Layer (SSL) | +# ------------------------------------------------------------------------------ + +# Rewrite secure requests properly to prevent SSL certificate warnings, e.g.: +# prevent `https://www.example.com` when your certificate only allows +# `https://secure.example.com`. + +# +# RewriteCond %{SERVER_PORT} !^443 +# RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L] +# + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +# Force client-side SSL redirection. + +# If a user types "example.com" in his browser, the above rule will redirect him +# to the secure version of the site. That still leaves a window of opportunity +# (the initial HTTP connection) for an attacker to downgrade or redirect the +# request. The following header ensures that browser will ONLY connect to your +# server via HTTPS, regardless of what the users type in the address bar. +# http://www.html5rocks.com/en/tutorials/security/transport-layer-security/ + +# +# Header set Strict-Transport-Security max-age=16070400; +# + +# ------------------------------------------------------------------------------ +# | Server software information | +# ------------------------------------------------------------------------------ + +# Avoid displaying the exact Apache version number, the description of the +# generic OS-type and the information about Apache's compiled-in modules. + +# ADD THIS DIRECTIVE IN THE `httpd.conf` AS IT WILL NOT WORK IN THE `.htaccess`! + +# ServerTokens Prod + + +# ############################################################################## +# # WEB PERFORMANCE # +# ############################################################################## + +# ------------------------------------------------------------------------------ +# | Compression | +# ------------------------------------------------------------------------------ + + + + # Force compression for mangled headers. + # http://developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping + + + SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding + RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding + + + + # Compress all output labeled with one of the following MIME-types + # (for Apache versions below 2.3.7, you don't need to enable `mod_filter` + # and can remove the `` and `` lines + # as `AddOutputFilterByType` is still in the core directives). + + AddOutputFilterByType DEFLATE application/atom+xml \ + application/javascript \ + application/json \ + application/rss+xml \ + application/vnd.ms-fontobject \ + application/x-font-ttf \ + application/x-web-app-manifest+json \ + application/xhtml+xml \ + application/xml \ + font/opentype \ + image/svg+xml \ + image/x-icon \ + text/css \ + text/html \ + text/plain \ + text/x-component \ + text/xml + + + + +# ------------------------------------------------------------------------------ +# | Content transformations | +# ------------------------------------------------------------------------------ + +# Prevent some of the mobile network providers from modifying the content of +# your site: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5. + +# +# Header set Cache-Control "no-transform" +# + +# ------------------------------------------------------------------------------ +# | ETag removal | +# ------------------------------------------------------------------------------ + +# Since we're sending far-future expires headers (see below), ETags can +# be removed: http://developer.yahoo.com/performance/rules.html#etags. + +# `FileETag None` is not enough for every server. + + Header unset ETag + + +FileETag None + +# ------------------------------------------------------------------------------ +# | Expires headers (for better cache control) | +# ------------------------------------------------------------------------------ + +# The following expires headers are set pretty far in the future. If you don't +# control versioning with filename-based cache busting, consider lowering the +# cache time for resources like CSS and JS to something like 1 week. + + + + ExpiresActive on + ExpiresDefault "access plus 1 month" + + # CSS + ExpiresByType text/css "access plus 1 year" + + # Data interchange + ExpiresByType application/json "access plus 0 seconds" + ExpiresByType application/xml "access plus 0 seconds" + ExpiresByType text/xml "access plus 0 seconds" + + # Favicon (cannot be renamed!) + ExpiresByType image/x-icon "access plus 1 week" + + # HTML components (HTCs) + ExpiresByType text/x-component "access plus 1 month" + + # HTML + ExpiresByType text/html "access plus 0 seconds" + + # JavaScript + ExpiresByType application/javascript "access plus 1 year" + + # Manifest files + ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds" + ExpiresByType text/cache-manifest "access plus 0 seconds" + + # Media + ExpiresByType audio/ogg "access plus 1 month" + ExpiresByType image/gif "access plus 1 month" + ExpiresByType image/jpeg "access plus 1 month" + ExpiresByType image/png "access plus 1 month" + ExpiresByType video/mp4 "access plus 1 month" + ExpiresByType video/ogg "access plus 1 month" + ExpiresByType video/webm "access plus 1 month" + + # Web feeds + ExpiresByType application/atom+xml "access plus 1 hour" + ExpiresByType application/rss+xml "access plus 1 hour" + + # Web fonts + ExpiresByType application/font-woff "access plus 1 month" + ExpiresByType application/vnd.ms-fontobject "access plus 1 month" + ExpiresByType application/x-font-ttf "access plus 1 month" + ExpiresByType font/opentype "access plus 1 month" + ExpiresByType image/svg+xml "access plus 1 month" + + + +# ------------------------------------------------------------------------------ +# | Filename-based cache busting | +# ------------------------------------------------------------------------------ + +# If you're not using a build process to manage your filename version revving, +# you might want to consider enabling the following directives to route all +# requests such as `/css/style.12345.css` to `/css/style.css`. + +# To understand why this is important and a better idea than `*.css?v231`, read: +# http://stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring + +# +# RewriteCond %{REQUEST_FILENAME} !-f +# RewriteCond %{REQUEST_FILENAME} !-d +# RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpg|gif)$ $1.$3 [L] +# + +# ------------------------------------------------------------------------------ +# | File concatenation | +# ------------------------------------------------------------------------------ + +# Allow concatenation from within specific CSS and JS files, e.g.: +# Inside of `script.combined.js` you could have +# +# +# and they would be included into this single file. + +# +# +# Options +Includes +# AddOutputFilterByType INCLUDES application/javascript application/json +# SetOutputFilter INCLUDES +# +# +# Options +Includes +# AddOutputFilterByType INCLUDES text/css +# SetOutputFilter INCLUDES +# +# + +# ------------------------------------------------------------------------------ +# | Persistent connections | +# ------------------------------------------------------------------------------ + +# Allow multiple requests to be sent over the same TCP connection: +# http://httpd.apache.org/docs/current/en/mod/core.html#keepalive. + +# Enable if you serve a lot of static content but, be aware of the +# possible disadvantages! + +# +# Header set Connection Keep-Alive +# diff --git a/__html/app/favicon.ico b/__html/app/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..372714a41ac4953a6d652ce2a4093565bb013a6e GIT binary patch literal 6782 zcmeH~OKc5M7{^bw+)5+$el(95G2*O6%oRMSfLS%Cenq44Pqf}6BcwqB7%g7 zorQ&0LPO-H6+%zNBOV*cMGz%Y;vIVZ{^!mxxt;6Y#no8MX@2*c`Q|&{`R0GlnVA|> z#9wu_;kU{(R~R$i7{jS!4OV{FCZ$dE8z~Se5GfET5GfET5T-y6&Tg<1VK(qeO?kes z_gMwBHn(SB2TVy{SIxoZ;)=P>=YX9_OsO%q2#`P6 zl)FcD#o-9d8yFLe*YR(Sb`pCDy+)?{sD|5Mcfn=w{OXh0Tzx}{X@L$n4Xc4bp)u?* zQ2mOz4*Q`7GLwazyFAkA3ba8i-Otr@ljBa91!d^M{b%Z@b5{ep*%@#j4&fVuodet9 zEF|GP%paJ?)u8_Mz~`7<4q8)VL36_xb`d;+ zfb}2^UjmEP)!d974PLC@SJwHY5jX1MzhZmg4xEI|Pz!6}BD{syAT6GP#t=W?1eAmF zN+XS_xmyfZLG?AlIZ&TdQ1xdmsh-THId}rL3Hrbv&$mDEy#mdH_QGL!2mbY-{f=LA zwgQfV?pZp01mzJLL-(S7TY#~(2L9IE{gx2B4jw{q%;2%|CLvpWiv0|qAlNV4@de^M zy;Y;zcjzw7w9kW0KBmCf>97x;K|f^6T?oJQJ^V`Un>29Xl+XwZwFflL4d?)Ak_27Pbsqb28=myCNC)nRjW9K`ExZI@6}ElAI@|Es=1lp-1`QXoJul$5YRhw>}=@1J9%;x5SENODkJr*w)taM5U}LF)i2xs1DgCNCF>< jhJVJL<-^~&{t3@=L3yaV&$B5$hTVPm_MhBWhF-q_M7z&N literal 0 HcmV?d00001 diff --git a/__html/app/images/logo.svg b/__html/app/images/logo.svg new file mode 100644 index 0000000..31e11ac --- /dev/null +++ b/__html/app/images/logo.svg @@ -0,0 +1,50 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/__html/app/index.html b/__html/app/index.html new file mode 100644 index 0000000..6aa9128 --- /dev/null +++ b/__html/app/index.html @@ -0,0 +1,118 @@ + + + + + hyperfox live + + + + + + + + + + + + + + + + + + +
+ + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/__html/app/scripts/app.js b/__html/app/scripts/app.js new file mode 100644 index 0000000..8e7acad --- /dev/null +++ b/__html/app/scripts/app.js @@ -0,0 +1,49 @@ +'use strict'; + +/** + * @ngdoc overview + * @name webApp + * @description + * # webApp + * + * Main module of the application. + */ +angular + .module('webApp', [ + 'ngAnimate', + 'ngCookies', + 'ngResource', + 'ngRoute', + 'ngSanitize', + 'ngTouch' + //'luegg.directives' + ]) + .config(function ($routeProvider) { + $routeProvider + .when('/details/:id', { + templateUrl: 'views/details.html', + controller: 'DetailsCtrl' + }) + .when('/:page?', { + templateUrl: 'views/main.html', + controller: 'MainCtrl' + }) + .otherwise({ + redirectTo: '/#/' + }); + }) + .directive('tooltip', function(){ + return { + restrict: 'A', + link: function(scope, element, attrs) { + $(element).hover(function(){ + // on mouseenter + $(element).tooltip('show'); + }, function(){ + // on mouseleave + $(element).tooltip('hide'); + }); + } + }; + }); + ; diff --git a/__html/app/scripts/controllers/main.js b/__html/app/scripts/controllers/main.js new file mode 100644 index 0000000..85f3d96 --- /dev/null +++ b/__html/app/scripts/controllers/main.js @@ -0,0 +1,142 @@ +'use strict'; + +var ERR_HYPERFOX_NOT_RUNNING = 'Could not connect to the Hyperfox API. Seems like hyperfox is not running on your local box.'; + +/** + * @ngdoc function + * @name webApp.controller:MainCtrl + * @description + * # MainCtrl + * Controller of the webApp + */ +angular.module('webApp') + .controller('ParentCtrl', function($scope, $routeParams, api) { + + $scope.apierror = null; + + $scope.setTerms = function() { + $scope.$broadcast('search'); + }; + + }) + .controller('DetailsCtrl', function($scope, $routeParams, api) { + $scope.currentID = parseInt($routeParams.id, 10); + $scope.details = {}; + + api.get($scope.currentID).then(function(res) { + $scope.apierror = null; + + $scope.details = res; + }, function(reason) { + $scope.apierror = ERR_HYPERFOX_NOT_RUNNING; + }); + + $scope.$on('search', function() { + location.href = '/#/1'; + refresh(); + }); + + }) + .controller('MainCtrl', function($scope, $routeParams, api) { + + if ($routeParams.source) { + window.localStorage.setItem('source', $routeParams.source); + }; + + $scope.$on('search', function() { + location.href = '/#/'; + refresh(); + }); + + $scope.requests = []; + $scope.totalPages = 0; + $scope.currentPage = parseInt($routeParams.page || 1, 10); + + var pull = function(page, q) { + api.pull(page, q).then(function(res) { + $scope.apierror = null; + + $scope.requests = res.data; + $scope.totalPages = res.pages; + $scope.currentPage = res.page; + + }, function(reason) { + $scope.apierror = ERR_HYPERFOX_NOT_RUNNING; + }); + }; + + var refresh = function() { + pull($scope.currentPage, $scope.q); + }; + + setInterval( + function() { + refresh(); + }, + 10000 + ); + + refresh(); + }) + .filter('mime', function() { + return function(input) { + var c = input.indexOf(';'); + if (c >= 0) { + return input.substr(0, c); + }; + return input; + } + }) + .filter('origin', function() { + return function(input) { + if (input) { + var c = input.indexOf(':'); + if (c >= 0) { + return input.substr(0, c); + }; + } + return input; + } + }) + .filter('size', function() { + return function(input) { + if (!input) { + return '-'; + }; + var kb = 1024; + if (input < kb) { + return input + 'b'; + } else if (input < kb*kb) { + return (input/kb).toFixed(2) + 'Kb'; + } + return (input/(kb*kb)).toFixed(2) + 'Mb'; + } + }) + .filter('time', function() { + return function(input) { + if (input < 1e9) { + return (input/1e6).toFixed(2) + 'ms'; + }; + return (input/1e9).toFixed(2) + 's'; + } + }) + .filter('api_request', function() { + return function(input) { + return endpoint(input); + } + }) + .filter('pageRange', function() { + return function(input, current, total, size) { + var sz = 3; + + var lo = Math.max(1, current - sz); + var hi = Math.min(total, current + sz); + + var i; + for (i = lo; i <= hi; i++) { + input.push(i); + }; + + return input; + }; + }); diff --git a/__html/app/scripts/services/main.js b/__html/app/scripts/services/main.js new file mode 100644 index 0000000..8f2b071 --- /dev/null +++ b/__html/app/scripts/services/main.js @@ -0,0 +1,62 @@ +'use strict'; + +function endpoint(url) { + var prefix = window.localStorage.getItem('source'); + + if (!prefix) { + prefix = '127.0.0.1:3030'; + }; + + return 'http://' + prefix + url; +} + +var downloadLink = function(id) { + return endpoint('/download?id='+id); +}; + +angular.module('webApp') + .service('api', function($http) { + var api = {}; + + api.get = function(id) { + var req = { + 'method': 'POST', + 'url': endpoint('/get'), + 'data': $.param({ + 'id': id + }), + 'headers': { + 'Content-Type': 'application/x-www-form-urlencoded' + } + }; + + var promise = $http(req).then(function(res) { + return res.data; + }); + + return promise; + }; + + api.pull = function(page, q) { + + var req = { + 'method': 'POST', + 'url': endpoint('/pull'), + 'data': $.param({ + 'page': page, + 'q': q || '' + }), + 'headers': { + 'Content-Type': 'application/x-www-form-urlencoded' + } + }; + + var promise = $http(req).then(function(res) { + return res.data; + }); + + return promise; + }; + + return api; + }); diff --git a/__html/app/styles/main.scss b/__html/app/styles/main.scss new file mode 100644 index 0000000..34c40ff --- /dev/null +++ b/__html/app/styles/main.scss @@ -0,0 +1,197 @@ +$icon-font-path: "../bower_components/bootstrap-sass-official/assets/fonts/bootstrap/"; +// bower:scss +@import "bootstrap-sass-official/assets/stylesheets/_bootstrap.scss"; +// endbower + +.browsehappy { + margin: 0.2em 0; + background: #ccc; + color: #000; + padding: 0.2em 0; +} + +/* Space out content a bit */ +body { + padding-top: 70px; + padding-bottom: 20px; +} + +/* Everything but the jumbotron gets side spacing for mobile first views */ +.header, +.marketing, +.footer { + padding-left: 15px; + padding-right: 15px; +} + +/* Custom page header */ +.header { + border-bottom: 1px solid #e5e5e5; + + /* Make the masthead heading the same height as the navigation */ + h3 { + margin-top: 0; + margin-bottom: 0; + line-height: 40px; + padding-bottom: 19px; + } +} + +/* Custom page footer */ +.footer { + padding-top: 19px; + color: #777; + border-top: 1px solid #e5e5e5; +} + +.container-narrow > hr { + margin: 30px 0; +} + +/* Main marketing message and sign up button */ +.jumbotron { + text-align: center; + border-bottom: 1px solid #e5e5e5; + + .btn { + font-size: 21px; + padding: 14px 24px; + } +} + +/* Supporting marketing content */ +.marketing { + margin: 40px 0; + + p + h4 { + margin-top: 28px; + } +} + +/* Responsive: Portrait tablets and up */ +@media screen and (min-width: 768px) { + .container { + max-width: 730px; + } + + /* Remove the padding we set earlier */ + .header, + .marketing, + .footer { + padding-left: 0; + padding-right: 0; + } + /* Space out the masthead */ + .header { + margin-bottom: 30px; + } + /* Remove the bottom border on the jumbotron for visual effect */ + .jumbotron { + border-bottom: 0; + } +} +#requests-paginator { + margin-left: 10px; + margin-right: 10px; + position: fixed; + bottom: 10px; +} +#requests-paginator ul { + margin: 0px; + padding: 0px; +} +#details-wrapper { + height: auto; +} +#details-wrapper dd { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +.container { + max-width: 100%; +} +.data-rows { + height: auto; + overflow-y: scroll; + position: fixed; + top: 50px; + left: 0px; + right: 0px; + bottom: 65px; +} +.content-fixed { + position: fixed; + top: 0px; + left: 0px; + bottom: 0px; + right: 0px; +} +.content-fluid { + width: 100%; +} +#requests-wrapper th { + text-align: center; +} + +#requests-wrapper th.th-scheme { + width: 80px; +} +#requests-wrapper th.th-path { + width: 300px; +} +#requests-wrapper th.th-type { + width: 120px; +} +#requests-wrapper th.th-direction { + width: 100px; +} +#requests-wrapper th.th-host { + width: 200px; +} +#requests-wrapper th.th-method { + width: 80px; +} +#requests-wrapper th.th-origin { + width: 120px; +} +#requests-wrapper tbody td { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +#requests-wrapper td.td-path { + max-width: 300px; +} +#requests-wrapper td.td-host { + max-width: 200px; +} +#requests-wrapper td.td-scheme { + text-align: center; +} +#requests-wrapper td.td-type { + max-width: 120px; + text-align: center; +} +#requests-wrapper td.td-origin { + max-width: 150px; +} +#requests-wrapper td.td-method { + text-align: center; +} +#requests-wrapper td.td-status { + text-align: center; +} +#requests-wrapper td.td-size { + text-align: center; +} +#requests-wrapper td.td-actions { + text-align: center; +} +.navbar-brand img { + display: inline; +} +.buttons { + text-align: right; +} diff --git a/__html/app/views/details.html b/__html/app/views/details.html new file mode 100644 index 0000000..213b50f --- /dev/null +++ b/__html/app/views/details.html @@ -0,0 +1,70 @@ +
+
+ + + +
+ +

{{details.origin | origin}} -> {{details.host}}

+ +

Abstract

+ +

+ On {{details.date_start | date: 'MMM d, y H:mm:ss'}} a + {{details.method}} request was issued to {{details.host}} by + {{details.origin | origin}}. +

+

+ The request had a size of {{details.content_length | size}} and took + {{details.time_taken | time}} to complete. +

+

+ The request took {{details.time_taken | time}} to complete. +

+ +

+
+ +
+ +
+
+
+ + +
+
+ +

+ + Server response +

+ +
+ + +
{{header}}
+
{{value}}
+
+
+
+ +

+ + Client request +

+ +
+ + +
{{header}}
+
{{value}}
+
+
+
+
+ +
+
diff --git a/__html/app/views/main.html b/__html/app/views/main.html new file mode 100644 index 0000000..1e2b241 --- /dev/null +++ b/__html/app/views/main.html @@ -0,0 +1,108 @@ + + + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ + + +
+
diff --git a/__html/bower.json b/__html/bower.json new file mode 100644 index 0000000..f33a5b7 --- /dev/null +++ b/__html/bower.json @@ -0,0 +1,22 @@ +{ + "name": "web", + "version": "0.0.0", + "dependencies": { + "angular": "^1.3.0", + "json3": "^3.3.0", + "es5-shim": "^4.0.0", + "bootstrap-sass-official": "^3.2.0", + "angular-animate": "^1.3.0", + "angular-cookies": "^1.3.0", + "angular-resource": "^1.3.0", + "angular-route": "^1.3.0", + "angular-sanitize": "^1.3.0", + "angular-touch": "^1.3.0", + "angularjs-scroll-glue-Luegg": "~2.0.3" + }, + "devDependencies": { + "angular-mocks": "~1.3.0", + "angular-scenario": "~1.3.0" + }, + "appPath": "app" +} diff --git a/__html/package.json b/__html/package.json new file mode 100644 index 0000000..03d9e6b --- /dev/null +++ b/__html/package.json @@ -0,0 +1,44 @@ +{ + "name": "web", + "version": "0.0.0", + "dependencies": { + "grunt": "~0.4.5" + }, + "devDependencies": { + "grunt": "^0.4.1", + "grunt-autoprefixer": "^0.7.3", + "grunt-concurrent": "^0.5.0", + "grunt-contrib-clean": "^0.5.0", + "grunt-contrib-compass": "~1.0.1", + "grunt-contrib-concat": "^0.4.0", + "grunt-contrib-connect": "^0.7.1", + "grunt-contrib-copy": "^0.5.0", + "grunt-contrib-cssmin": "^0.9.0", + "grunt-contrib-htmlmin": "^0.3.0", + "grunt-contrib-imagemin": "^0.8.1", + "grunt-contrib-jshint": "^0.10.0", + "grunt-contrib-uglify": "^0.4.0", + "grunt-contrib-watch": "^0.6.1", + "grunt-filerev": "^0.2.1", + "grunt-google-cdn": "^0.4.0", + "grunt-karma": "^0.9.0", + "grunt-newer": "^0.7.0", + "grunt-ng-annotate": "^0.4.0", + "grunt-svgmin": "^0.4.0", + "grunt-usemin": "^2.1.1", + "grunt-wiredep": "^1.7.0", + "jasmine-core": "^2.1.3", + "jshint-stylish": "^0.2.0", + "karma": "^0.12.28", + "karma-jasmine": "^0.3.2", + "karma-phantomjs-launcher": "^0.1.4", + "load-grunt-tasks": "^0.4.0", + "time-grunt": "^0.3.1" + }, + "engines": { + "node": ">=0.10.0" + }, + "scripts": { + "test": "grunt test" + } +} diff --git a/__html/test/.jshintrc b/__html/test/.jshintrc new file mode 100644 index 0000000..b1be025 --- /dev/null +++ b/__html/test/.jshintrc @@ -0,0 +1,36 @@ +{ + "node": true, + "browser": true, + "esnext": true, + "bitwise": true, + "camelcase": true, + "curly": true, + "eqeqeq": true, + "immed": true, + "indent": 2, + "latedef": true, + "newcap": true, + "noarg": true, + "quotmark": "single", + "regexp": true, + "undef": true, + "unused": true, + "strict": true, + "trailing": true, + "smarttabs": true, + "globals": { + "after": false, + "afterEach": false, + "angular": false, + "before": false, + "beforeEach": false, + "browser": false, + "describe": false, + "expect": false, + "inject": false, + "it": false, + "jasmine": false, + "spyOn": false + } +} + diff --git a/__html/test/karma.conf.js b/__html/test/karma.conf.js new file mode 100644 index 0000000..5242282 --- /dev/null +++ b/__html/test/karma.conf.js @@ -0,0 +1,75 @@ +// Karma configuration +// http://karma-runner.github.io/0.12/config/configuration-file.html +// Generated on 2014-12-20 using +// generator-karma 0.8.3 + +module.exports = function(config) { + 'use strict'; + + config.set({ + // enable / disable watching file and executing tests whenever any file changes + autoWatch: true, + + // base path, that will be used to resolve files and exclude + basePath: '../', + + // testing framework to use (jasmine/mocha/qunit/...) + frameworks: ['jasmine'], + + // list of files / patterns to load in the browser + files: [ + 'bower_components/angular/angular.js', + 'bower_components/angular-mocks/angular-mocks.js', + 'bower_components/angular-animate/angular-animate.js', + 'bower_components/angular-cookies/angular-cookies.js', + 'bower_components/angular-resource/angular-resource.js', + 'bower_components/angular-route/angular-route.js', + 'bower_components/angular-sanitize/angular-sanitize.js', + 'bower_components/angular-touch/angular-touch.js', + 'app/scripts/**/*.js', + 'test/mock/**/*.js', + 'test/spec/**/*.js' + ], + + // list of files / patterns to exclude + exclude: [], + + // web server port + port: 8080, + + // Start these browsers, currently available: + // - Chrome + // - ChromeCanary + // - Firefox + // - Opera + // - Safari (only Mac) + // - PhantomJS + // - IE (only Windows) + browsers: [ + 'PhantomJS' + ], + + // Which plugins to enable + plugins: [ + 'karma-phantomjs-launcher', + 'karma-jasmine' + ], + + // Continuous Integration mode + // if true, it capture browsers, run tests and exit + singleRun: false, + + colors: true, + + // level of logging + // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG + logLevel: config.LOG_INFO, + + // Uncomment the following lines if you are using grunt's server to run the tests + // proxies: { + // '/': 'http://localhost:9000/' + // }, + // URL root prevent conflicts with the site root + // urlRoot: '_karma_' + }); +}; diff --git a/__html/test/spec/controllers/about.js b/__html/test/spec/controllers/about.js new file mode 100644 index 0000000..2366696 --- /dev/null +++ b/__html/test/spec/controllers/about.js @@ -0,0 +1,22 @@ +'use strict'; + +describe('Controller: AboutCtrl', function () { + + // load the controller's module + beforeEach(module('webApp')); + + var AboutCtrl, + scope; + + // Initialize the controller and a mock scope + beforeEach(inject(function ($controller, $rootScope) { + scope = $rootScope.$new(); + AboutCtrl = $controller('AboutCtrl', { + $scope: scope + }); + })); + + it('should attach a list of awesomeThings to the scope', function () { + expect(scope.awesomeThings.length).toBe(3); + }); +}); diff --git a/__html/test/spec/controllers/main.js b/__html/test/spec/controllers/main.js new file mode 100644 index 0000000..482025b --- /dev/null +++ b/__html/test/spec/controllers/main.js @@ -0,0 +1,22 @@ +'use strict'; + +describe('Controller: MainCtrl', function () { + + // load the controller's module + beforeEach(module('webApp')); + + var MainCtrl, + scope; + + // Initialize the controller and a mock scope + beforeEach(inject(function ($controller, $rootScope) { + scope = $rootScope.$new(); + MainCtrl = $controller('MainCtrl', { + $scope: scope + }); + })); + + it('should attach a list of awesomeThings to the scope', function () { + expect(scope.awesomeThings.length).toBe(3); + }); +}); From 1d21e44d14d6e6076f787a3817680438e5a2ccbf Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Fri, 10 Jun 2016 22:32:00 -0500 Subject: [PATCH 02/34] Move old version to another folder --- html/.bowerrc | 3 - html/.editorconfig | 21 -- html/.gitattributes | 1 - html/.gitignore | 6 - html/.jshintrc | 23 -- html/.travis.yml | 6 - html/Gruntfile.js | 441 ---------------------- html/Makefile | 6 - html/app/.buildignore | 1 - html/app/.htaccess | 543 --------------------------- html/app/favicon.ico | Bin 6782 -> 0 bytes html/app/images/logo.svg | 50 --- html/app/index.html | 118 ------ html/app/scripts/app.js | 49 --- html/app/scripts/controllers/main.js | 142 ------- html/app/scripts/services/main.js | 62 --- html/app/styles/main.scss | 197 ---------- html/app/views/details.html | 70 ---- html/app/views/main.html | 108 ------ html/bower.json | 22 -- html/package.json | 44 --- html/test/.jshintrc | 36 -- html/test/karma.conf.js | 75 ---- html/test/spec/controllers/about.js | 22 -- html/test/spec/controllers/main.js | 22 -- 25 files changed, 2068 deletions(-) delete mode 100644 html/.bowerrc delete mode 100644 html/.editorconfig delete mode 100644 html/.gitattributes delete mode 100644 html/.gitignore delete mode 100644 html/.jshintrc delete mode 100644 html/.travis.yml delete mode 100644 html/Gruntfile.js delete mode 100644 html/Makefile delete mode 100644 html/app/.buildignore delete mode 100644 html/app/.htaccess delete mode 100644 html/app/favicon.ico delete mode 100644 html/app/images/logo.svg delete mode 100644 html/app/index.html delete mode 100644 html/app/scripts/app.js delete mode 100644 html/app/scripts/controllers/main.js delete mode 100644 html/app/scripts/services/main.js delete mode 100644 html/app/styles/main.scss delete mode 100644 html/app/views/details.html delete mode 100644 html/app/views/main.html delete mode 100644 html/bower.json delete mode 100644 html/package.json delete mode 100644 html/test/.jshintrc delete mode 100644 html/test/karma.conf.js delete mode 100644 html/test/spec/controllers/about.js delete mode 100644 html/test/spec/controllers/main.js diff --git a/html/.bowerrc b/html/.bowerrc deleted file mode 100644 index 69fad35..0000000 --- a/html/.bowerrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "directory": "bower_components" -} diff --git a/html/.editorconfig b/html/.editorconfig deleted file mode 100644 index c2cdfb8..0000000 --- a/html/.editorconfig +++ /dev/null @@ -1,21 +0,0 @@ -# EditorConfig helps developers define and maintain consistent -# coding styles between different editors and IDEs -# editorconfig.org - -root = true - - -[*] - -# Change these settings to your own preference -indent_style = space -indent_size = 2 - -# We recommend you to keep these unchanged -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true - -[*.md] -trim_trailing_whitespace = false diff --git a/html/.gitattributes b/html/.gitattributes deleted file mode 100644 index 2125666..0000000 --- a/html/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -* text=auto \ No newline at end of file diff --git a/html/.gitignore b/html/.gitignore deleted file mode 100644 index 980a1aa..0000000 --- a/html/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -node_modules -*.swp -dist -.tmp -.sass-cache -bower_components diff --git a/html/.jshintrc b/html/.jshintrc deleted file mode 100644 index f750969..0000000 --- a/html/.jshintrc +++ /dev/null @@ -1,23 +0,0 @@ -{ - "node": true, - "browser": true, - "esnext": true, - "bitwise": true, - "camelcase": true, - "curly": true, - "eqeqeq": true, - "immed": true, - "indent": 2, - "latedef": true, - "newcap": true, - "noarg": true, - "quotmark": "single", - "undef": true, - "unused": true, - "strict": true, - "trailing": true, - "smarttabs": true, - "globals": { - "angular": false - } -} diff --git a/html/.travis.yml b/html/.travis.yml deleted file mode 100644 index a80b6e0..0000000 --- a/html/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -language: node_js -node_js: - - '0.10' -before_script: - - 'npm install -g bower grunt-cli' - - 'bower install' diff --git a/html/Gruntfile.js b/html/Gruntfile.js deleted file mode 100644 index 737d49a..0000000 --- a/html/Gruntfile.js +++ /dev/null @@ -1,441 +0,0 @@ -// Generated on 2014-12-20 using generator-angular 0.10.0 -'use strict'; - -// # Globbing -// for performance reasons we're only matching one level down: -// 'test/spec/{,*/}*.js' -// use this if you want to recursively match all subfolders: -// 'test/spec/**/*.js' - -module.exports = function (grunt) { - - // Load grunt tasks automatically - require('load-grunt-tasks')(grunt); - - // Time how long tasks take. Can help when optimizing build times - require('time-grunt')(grunt); - - // Configurable paths for the application - var appConfig = { - app: require('./bower.json').appPath || 'app', - dist: 'dist' - }; - - // Define the configuration for all the tasks - grunt.initConfig({ - - // Project settings - yeoman: appConfig, - - // Watches files for changes and runs tasks based on the changed files - watch: { - bower: { - files: ['bower.json'], - tasks: ['wiredep'] - }, - js: { - files: ['<%= yeoman.app %>/scripts/{,*/}*.js'], - tasks: ['newer:jshint:all'], - options: { - livereload: '<%= connect.options.livereload %>' - } - }, - jsTest: { - files: ['test/spec/{,*/}*.js'], - tasks: ['newer:jshint:test', 'karma'] - }, - compass: { - files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'], - tasks: ['compass:server', 'autoprefixer'] - }, - gruntfile: { - files: ['Gruntfile.js'] - }, - livereload: { - options: { - livereload: '<%= connect.options.livereload %>' - }, - files: [ - '<%= yeoman.app %>/{,*/}*.html', - '.tmp/styles/{,*/}*.css', - '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}' - ] - } - }, - - // The actual grunt server settings - connect: { - options: { - port: 9000, - // Change this to '0.0.0.0' to access the server from outside. - hostname: 'localhost', - livereload: 35729 - }, - livereload: { - options: { - open: true, - middleware: function (connect) { - return [ - connect.static('.tmp'), - connect().use( - '/bower_components', - connect.static('./bower_components') - ), - connect.static(appConfig.app) - ]; - } - } - }, - test: { - options: { - port: 9001, - middleware: function (connect) { - return [ - connect.static('.tmp'), - connect.static('test'), - connect().use( - '/bower_components', - connect.static('./bower_components') - ), - connect.static(appConfig.app) - ]; - } - } - }, - dist: { - options: { - open: true, - base: '<%= yeoman.dist %>' - } - } - }, - - // Make sure code styles are up to par and there are no obvious mistakes - jshint: { - options: { - jshintrc: '.jshintrc', - reporter: require('jshint-stylish') - }, - all: { - src: [ - 'Gruntfile.js', - '<%= yeoman.app %>/scripts/{,*/}*.js' - ] - }, - test: { - options: { - jshintrc: 'test/.jshintrc' - }, - src: ['test/spec/{,*/}*.js'] - } - }, - - // Empties folders to start fresh - clean: { - dist: { - files: [{ - dot: true, - src: [ - '.tmp', - '<%= yeoman.dist %>/{,*/}*', - '!<%= yeoman.dist %>/.git{,*/}*' - ] - }] - }, - server: '.tmp' - }, - - // Add vendor prefixed styles - autoprefixer: { - options: { - browsers: ['last 1 version'] - }, - dist: { - files: [{ - expand: true, - cwd: '.tmp/styles/', - src: '{,*/}*.css', - dest: '.tmp/styles/' - }] - } - }, - - // Automatically inject Bower components into the app - wiredep: { - app: { - src: ['<%= yeoman.app %>/index.html'], - ignorePath: /\.\.\// - }, - sass: { - src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'], - ignorePath: /(\.\.\/){1,2}bower_components\// - } - }, - - // Compiles Sass to CSS and generates necessary files if requested - compass: { - options: { - sassDir: '<%= yeoman.app %>/styles', - cssDir: '.tmp/styles', - generatedImagesDir: '.tmp/images/generated', - imagesDir: '<%= yeoman.app %>/images', - javascriptsDir: '<%= yeoman.app %>/scripts', - fontsDir: '<%= yeoman.app %>/styles/fonts', - importPath: './bower_components', - httpImagesPath: '/images', - httpGeneratedImagesPath: '/images/generated', - httpFontsPath: '/styles/fonts', - relativeAssets: false, - assetCacheBuster: false, - raw: 'Sass::Script::Number.precision = 10\n' - }, - dist: { - options: { - generatedImagesDir: '<%= yeoman.dist %>/images/generated' - } - }, - server: { - options: { - debugInfo: true - } - } - }, - - // Renames files for browser caching purposes - filerev: { - dist: { - src: [ - '<%= yeoman.dist %>/scripts/{,*/}*.js', - '<%= yeoman.dist %>/styles/{,*/}*.css', - '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}', - '<%= yeoman.dist %>/styles/fonts/*' - ] - } - }, - - // Reads HTML for usemin blocks to enable smart builds that automatically - // concat, minify and revision files. Creates configurations in memory so - // additional tasks can operate on them - useminPrepare: { - html: '<%= yeoman.app %>/index.html', - options: { - dest: '<%= yeoman.dist %>', - flow: { - html: { - steps: { - js: ['concat', 'uglifyjs'], - css: ['cssmin'] - }, - post: {} - } - } - } - }, - - // Performs rewrites based on filerev and the useminPrepare configuration - usemin: { - html: ['<%= yeoman.dist %>/{,*/}*.html'], - css: ['<%= yeoman.dist %>/styles/{,*/}*.css'], - options: { - assetsDirs: ['<%= yeoman.dist %>','<%= yeoman.dist %>/images'] - } - }, - - // The following *-min tasks will produce minified files in the dist folder - // By default, your `index.html`'s will take care of - // minification. These next options are pre-configured if you do not wish - // to use the Usemin blocks. - // cssmin: { - // dist: { - // files: { - // '<%= yeoman.dist %>/styles/main.css': [ - // '.tmp/styles/{,*/}*.css' - // ] - // } - // } - // }, - // uglify: { - // dist: { - // files: { - // '<%= yeoman.dist %>/scripts/scripts.js': [ - // '<%= yeoman.dist %>/scripts/scripts.js' - // ] - // } - // } - // }, - // concat: { - // dist: {} - // }, - - imagemin: { - dist: { - files: [{ - expand: true, - cwd: '<%= yeoman.app %>/images', - src: '{,*/}*.{png,jpg,jpeg,gif}', - dest: '<%= yeoman.dist %>/images' - }] - } - }, - - svgmin: { - dist: { - files: [{ - expand: true, - cwd: '<%= yeoman.app %>/images', - src: '{,*/}*.svg', - dest: '<%= yeoman.dist %>/images' - }] - } - }, - - htmlmin: { - dist: { - options: { - collapseWhitespace: true, - conservativeCollapse: true, - collapseBooleanAttributes: true, - removeCommentsFromCDATA: true, - removeOptionalTags: true - }, - files: [{ - expand: true, - cwd: '<%= yeoman.dist %>', - src: ['*.html', 'views/{,*/}*.html'], - dest: '<%= yeoman.dist %>' - }] - } - }, - - // ng-annotate tries to make the code safe for minification automatically - // by using the Angular long form for dependency injection. - ngAnnotate: { - dist: { - files: [{ - expand: true, - cwd: '.tmp/concat/scripts', - src: ['*.js', '!oldieshim.js'], - dest: '.tmp/concat/scripts' - }] - } - }, - - // Replace Google CDN references - cdnify: { - dist: { - html: ['<%= yeoman.dist %>/*.html'] - } - }, - - // Copies remaining files to places other tasks can use - copy: { - dist: { - files: [{ - expand: true, - dot: true, - cwd: '<%= yeoman.app %>', - dest: '<%= yeoman.dist %>', - src: [ - '*.{ico,png,txt}', - '.htaccess', - '*.html', - 'views/{,*/}*.html', - 'images/{,*/}*.{webp}', - 'fonts/{,*/}*.*' - ] - }, { - expand: true, - cwd: '.tmp/images', - dest: '<%= yeoman.dist %>/images', - src: ['generated/*'] - }, { - expand: true, - cwd: '.', - src: 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*', - dest: '<%= yeoman.dist %>' - }] - }, - styles: { - expand: true, - cwd: '<%= yeoman.app %>/styles', - dest: '.tmp/styles/', - src: '{,*/}*.css' - } - }, - - // Run some tasks in parallel to speed up the build process - concurrent: { - server: [ - 'compass:server' - ], - test: [ - 'compass' - ], - dist: [ - 'compass:dist', - 'imagemin', - 'svgmin' - ] - }, - - // Test settings - karma: { - unit: { - configFile: 'test/karma.conf.js', - singleRun: true - } - } - }); - - - grunt.registerTask('serve', 'Compile then start a connect web server', function (target) { - if (target === 'dist') { - return grunt.task.run(['build', 'connect:dist:keepalive']); - } - - grunt.task.run([ - 'clean:server', - 'wiredep', - 'concurrent:server', - 'autoprefixer', - 'connect:livereload', - 'watch' - ]); - }); - - grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) { - grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.'); - grunt.task.run(['serve:' + target]); - }); - - grunt.registerTask('test', [ - 'clean:server', - 'concurrent:test', - 'autoprefixer', - 'connect:test', - 'karma' - ]); - - grunt.registerTask('build', [ - 'clean:dist', - 'wiredep', - 'useminPrepare', - 'concurrent:dist', - 'autoprefixer', - 'concat', - 'ngAnnotate', - 'copy:dist', - 'cdnify', - 'cssmin', - 'uglify', - 'filerev', - 'usemin', - 'htmlmin' - ]); - - grunt.registerTask('default', [ - 'newer:jshint', - 'test', - 'build' - ]); -}; diff --git a/html/Makefile b/html/Makefile deleted file mode 100644 index 64337a5..0000000 --- a/html/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -clean: - grunt clean - -publish: clean - grunt build - scp -r dist/* www-data@hyperfox.org:/var/www/hyperfox.org/live/ diff --git a/html/app/.buildignore b/html/app/.buildignore deleted file mode 100644 index fc98b8e..0000000 --- a/html/app/.buildignore +++ /dev/null @@ -1 +0,0 @@ -*.coffee \ No newline at end of file diff --git a/html/app/.htaccess b/html/app/.htaccess deleted file mode 100644 index cb84cb9..0000000 --- a/html/app/.htaccess +++ /dev/null @@ -1,543 +0,0 @@ -# Apache Configuration File - -# (!) Using `.htaccess` files slows down Apache, therefore, if you have access -# to the main server config file (usually called `httpd.conf`), you should add -# this logic there: http://httpd.apache.org/docs/current/howto/htaccess.html. - -# ############################################################################## -# # CROSS-ORIGIN RESOURCE SHARING (CORS) # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | Cross-domain AJAX requests | -# ------------------------------------------------------------------------------ - -# Enable cross-origin AJAX requests. -# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity -# http://enable-cors.org/ - -# -# Header set Access-Control-Allow-Origin "*" -# - -# ------------------------------------------------------------------------------ -# | CORS-enabled images | -# ------------------------------------------------------------------------------ - -# Send the CORS header for images when browsers request it. -# https://developer.mozilla.org/en/CORS_Enabled_Image -# http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html -# http://hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/ - - - - - SetEnvIf Origin ":" IS_CORS - Header set Access-Control-Allow-Origin "*" env=IS_CORS - - - - -# ------------------------------------------------------------------------------ -# | Web fonts access | -# ------------------------------------------------------------------------------ - -# Allow access from all domains for web fonts - - - - Header set Access-Control-Allow-Origin "*" - - - - -# ############################################################################## -# # ERRORS # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | 404 error prevention for non-existing redirected folders | -# ------------------------------------------------------------------------------ - -# Prevent Apache from returning a 404 error for a rewrite if a directory -# with the same name does not exist. -# http://httpd.apache.org/docs/current/content-negotiation.html#multiviews -# http://www.webmasterworld.com/apache/3808792.htm - -Options -MultiViews - -# ------------------------------------------------------------------------------ -# | Custom error messages / pages | -# ------------------------------------------------------------------------------ - -# You can customize what Apache returns to the client in case of an error (see -# http://httpd.apache.org/docs/current/mod/core.html#errordocument), e.g.: - -ErrorDocument 404 /404.html - - -# ############################################################################## -# # INTERNET EXPLORER # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | Better website experience | -# ------------------------------------------------------------------------------ - -# Force IE to render pages in the highest available mode in the various -# cases when it may not: http://hsivonen.iki.fi/doctype/ie-mode.pdf. - - - Header set X-UA-Compatible "IE=edge" - # `mod_headers` can't match based on the content-type, however, we only - # want to send this header for HTML pages and not for the other resources - - Header unset X-UA-Compatible - - - -# ------------------------------------------------------------------------------ -# | Cookie setting from iframes | -# ------------------------------------------------------------------------------ - -# Allow cookies to be set from iframes in IE. - -# -# Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"" -# - -# ------------------------------------------------------------------------------ -# | Screen flicker | -# ------------------------------------------------------------------------------ - -# Stop screen flicker in IE on CSS rollovers (this only works in -# combination with the `ExpiresByType` directives for images from below). - -# BrowserMatch "MSIE" brokenvary=1 -# BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1 -# BrowserMatch "Opera" !brokenvary -# SetEnvIf brokenvary 1 force-no-vary - - -# ############################################################################## -# # MIME TYPES AND ENCODING # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | Proper MIME types for all files | -# ------------------------------------------------------------------------------ - - - - # Audio - AddType audio/mp4 m4a f4a f4b - AddType audio/ogg oga ogg - - # JavaScript - # Normalize to standard type (it's sniffed in IE anyways): - # http://tools.ietf.org/html/rfc4329#section-7.2 - AddType application/javascript js jsonp - AddType application/json json - - # Video - AddType video/mp4 mp4 m4v f4v f4p - AddType video/ogg ogv - AddType video/webm webm - AddType video/x-flv flv - - # Web fonts - AddType application/font-woff woff - AddType application/vnd.ms-fontobject eot - - # Browsers usually ignore the font MIME types and sniff the content, - # however, Chrome shows a warning if other MIME types are used for the - # following fonts. - AddType application/x-font-ttf ttc ttf - AddType font/opentype otf - - # Make SVGZ fonts work on iPad: - # https://twitter.com/FontSquirrel/status/14855840545 - AddType image/svg+xml svg svgz - AddEncoding gzip svgz - - # Other - AddType application/octet-stream safariextz - AddType application/x-chrome-extension crx - AddType application/x-opera-extension oex - AddType application/x-shockwave-flash swf - AddType application/x-web-app-manifest+json webapp - AddType application/x-xpinstall xpi - AddType application/xml atom rdf rss xml - AddType image/webp webp - AddType image/x-icon ico - AddType text/cache-manifest appcache manifest - AddType text/vtt vtt - AddType text/x-component htc - AddType text/x-vcard vcf - - - -# ------------------------------------------------------------------------------ -# | UTF-8 encoding | -# ------------------------------------------------------------------------------ - -# Use UTF-8 encoding for anything served as `text/html` or `text/plain`. -AddDefaultCharset utf-8 - -# Force UTF-8 for certain file formats. - - AddCharset utf-8 .atom .css .js .json .rss .vtt .webapp .xml - - - -# ############################################################################## -# # URL REWRITES # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | Rewrite engine | -# ------------------------------------------------------------------------------ - -# Turning on the rewrite engine and enabling the `FollowSymLinks` option is -# necessary for the following directives to work. - -# If your web host doesn't allow the `FollowSymlinks` option, you may need to -# comment it out and use `Options +SymLinksIfOwnerMatch` but, be aware of the -# performance impact: http://httpd.apache.org/docs/current/misc/perf-tuning.html#symlinks - -# Also, some cloud hosting services require `RewriteBase` to be set: -# http://www.rackspace.com/knowledge_center/frequently-asked-question/why-is-mod-rewrite-not-working-on-my-site - - - Options +FollowSymlinks - # Options +SymLinksIfOwnerMatch - RewriteEngine On - # RewriteBase / - - -# ------------------------------------------------------------------------------ -# | Suppressing / Forcing the "www." at the beginning of URLs | -# ------------------------------------------------------------------------------ - -# The same content should never be available under two different URLs especially -# not with and without "www." at the beginning. This can cause SEO problems -# (duplicate content), therefore, you should choose one of the alternatives and -# redirect the other one. - -# By default option 1 (no "www.") is activated: -# http://no-www.org/faq.php?q=class_b - -# If you'd prefer to use option 2, just comment out all the lines from option 1 -# and uncomment the ones from option 2. - -# IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME! - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Option 1: rewrite www.example.com → example.com - - - RewriteCond %{HTTPS} !=on - RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] - RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L] - - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Option 2: rewrite example.com → www.example.com - -# Be aware that the following might not be a good idea if you use "real" -# subdomains for certain parts of your website. - -# -# RewriteCond %{HTTPS} !=on -# RewriteCond %{HTTP_HOST} !^www\..+$ [NC] -# RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L] -# - - -# ############################################################################## -# # SECURITY # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | Content Security Policy (CSP) | -# ------------------------------------------------------------------------------ - -# You can mitigate the risk of cross-site scripting and other content-injection -# attacks by setting a Content Security Policy which whitelists trusted sources -# of content for your site. - -# The example header below allows ONLY scripts that are loaded from the current -# site's origin (no inline scripts, no CDN, etc). This almost certainly won't -# work as-is for your site! - -# To get all the details you'll need to craft a reasonable policy for your site, -# read: http://html5rocks.com/en/tutorials/security/content-security-policy (or -# see the specification: http://w3.org/TR/CSP). - -# -# Header set Content-Security-Policy "script-src 'self'; object-src 'self'" -# -# Header unset Content-Security-Policy -# -# - -# ------------------------------------------------------------------------------ -# | File access | -# ------------------------------------------------------------------------------ - -# Block access to directories without a default document. -# Usually you should leave this uncommented because you shouldn't allow anyone -# to surf through every directory on your server (which may includes rather -# private places like the CMS's directories). - - - Options -Indexes - - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Block access to hidden files and directories. -# This includes directories used by version control systems such as Git and SVN. - - - RewriteCond %{SCRIPT_FILENAME} -d [OR] - RewriteCond %{SCRIPT_FILENAME} -f - RewriteRule "(^|/)\." - [F] - - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Block access to backup and source files. -# These files may be left by some text editors and can pose a great security -# danger when anyone has access to them. - - - Order allow,deny - Deny from all - Satisfy All - - -# ------------------------------------------------------------------------------ -# | Secure Sockets Layer (SSL) | -# ------------------------------------------------------------------------------ - -# Rewrite secure requests properly to prevent SSL certificate warnings, e.g.: -# prevent `https://www.example.com` when your certificate only allows -# `https://secure.example.com`. - -# -# RewriteCond %{SERVER_PORT} !^443 -# RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L] -# - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Force client-side SSL redirection. - -# If a user types "example.com" in his browser, the above rule will redirect him -# to the secure version of the site. That still leaves a window of opportunity -# (the initial HTTP connection) for an attacker to downgrade or redirect the -# request. The following header ensures that browser will ONLY connect to your -# server via HTTPS, regardless of what the users type in the address bar. -# http://www.html5rocks.com/en/tutorials/security/transport-layer-security/ - -# -# Header set Strict-Transport-Security max-age=16070400; -# - -# ------------------------------------------------------------------------------ -# | Server software information | -# ------------------------------------------------------------------------------ - -# Avoid displaying the exact Apache version number, the description of the -# generic OS-type and the information about Apache's compiled-in modules. - -# ADD THIS DIRECTIVE IN THE `httpd.conf` AS IT WILL NOT WORK IN THE `.htaccess`! - -# ServerTokens Prod - - -# ############################################################################## -# # WEB PERFORMANCE # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | Compression | -# ------------------------------------------------------------------------------ - - - - # Force compression for mangled headers. - # http://developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping - - - SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding - RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding - - - - # Compress all output labeled with one of the following MIME-types - # (for Apache versions below 2.3.7, you don't need to enable `mod_filter` - # and can remove the `` and `` lines - # as `AddOutputFilterByType` is still in the core directives). - - AddOutputFilterByType DEFLATE application/atom+xml \ - application/javascript \ - application/json \ - application/rss+xml \ - application/vnd.ms-fontobject \ - application/x-font-ttf \ - application/x-web-app-manifest+json \ - application/xhtml+xml \ - application/xml \ - font/opentype \ - image/svg+xml \ - image/x-icon \ - text/css \ - text/html \ - text/plain \ - text/x-component \ - text/xml - - - - -# ------------------------------------------------------------------------------ -# | Content transformations | -# ------------------------------------------------------------------------------ - -# Prevent some of the mobile network providers from modifying the content of -# your site: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5. - -# -# Header set Cache-Control "no-transform" -# - -# ------------------------------------------------------------------------------ -# | ETag removal | -# ------------------------------------------------------------------------------ - -# Since we're sending far-future expires headers (see below), ETags can -# be removed: http://developer.yahoo.com/performance/rules.html#etags. - -# `FileETag None` is not enough for every server. - - Header unset ETag - - -FileETag None - -# ------------------------------------------------------------------------------ -# | Expires headers (for better cache control) | -# ------------------------------------------------------------------------------ - -# The following expires headers are set pretty far in the future. If you don't -# control versioning with filename-based cache busting, consider lowering the -# cache time for resources like CSS and JS to something like 1 week. - - - - ExpiresActive on - ExpiresDefault "access plus 1 month" - - # CSS - ExpiresByType text/css "access plus 1 year" - - # Data interchange - ExpiresByType application/json "access plus 0 seconds" - ExpiresByType application/xml "access plus 0 seconds" - ExpiresByType text/xml "access plus 0 seconds" - - # Favicon (cannot be renamed!) - ExpiresByType image/x-icon "access plus 1 week" - - # HTML components (HTCs) - ExpiresByType text/x-component "access plus 1 month" - - # HTML - ExpiresByType text/html "access plus 0 seconds" - - # JavaScript - ExpiresByType application/javascript "access plus 1 year" - - # Manifest files - ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds" - ExpiresByType text/cache-manifest "access plus 0 seconds" - - # Media - ExpiresByType audio/ogg "access plus 1 month" - ExpiresByType image/gif "access plus 1 month" - ExpiresByType image/jpeg "access plus 1 month" - ExpiresByType image/png "access plus 1 month" - ExpiresByType video/mp4 "access plus 1 month" - ExpiresByType video/ogg "access plus 1 month" - ExpiresByType video/webm "access plus 1 month" - - # Web feeds - ExpiresByType application/atom+xml "access plus 1 hour" - ExpiresByType application/rss+xml "access plus 1 hour" - - # Web fonts - ExpiresByType application/font-woff "access plus 1 month" - ExpiresByType application/vnd.ms-fontobject "access plus 1 month" - ExpiresByType application/x-font-ttf "access plus 1 month" - ExpiresByType font/opentype "access plus 1 month" - ExpiresByType image/svg+xml "access plus 1 month" - - - -# ------------------------------------------------------------------------------ -# | Filename-based cache busting | -# ------------------------------------------------------------------------------ - -# If you're not using a build process to manage your filename version revving, -# you might want to consider enabling the following directives to route all -# requests such as `/css/style.12345.css` to `/css/style.css`. - -# To understand why this is important and a better idea than `*.css?v231`, read: -# http://stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring - -# -# RewriteCond %{REQUEST_FILENAME} !-f -# RewriteCond %{REQUEST_FILENAME} !-d -# RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpg|gif)$ $1.$3 [L] -# - -# ------------------------------------------------------------------------------ -# | File concatenation | -# ------------------------------------------------------------------------------ - -# Allow concatenation from within specific CSS and JS files, e.g.: -# Inside of `script.combined.js` you could have -# -# -# and they would be included into this single file. - -# -# -# Options +Includes -# AddOutputFilterByType INCLUDES application/javascript application/json -# SetOutputFilter INCLUDES -# -# -# Options +Includes -# AddOutputFilterByType INCLUDES text/css -# SetOutputFilter INCLUDES -# -# - -# ------------------------------------------------------------------------------ -# | Persistent connections | -# ------------------------------------------------------------------------------ - -# Allow multiple requests to be sent over the same TCP connection: -# http://httpd.apache.org/docs/current/en/mod/core.html#keepalive. - -# Enable if you serve a lot of static content but, be aware of the -# possible disadvantages! - -# -# Header set Connection Keep-Alive -# diff --git a/html/app/favicon.ico b/html/app/favicon.ico deleted file mode 100644 index 372714a41ac4953a6d652ce2a4093565bb013a6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6782 zcmeH~OKc5M7{^bw+)5+$el(95G2*O6%oRMSfLS%Cenq44Pqf}6BcwqB7%g7 zorQ&0LPO-H6+%zNBOV*cMGz%Y;vIVZ{^!mxxt;6Y#no8MX@2*c`Q|&{`R0GlnVA|> z#9wu_;kU{(R~R$i7{jS!4OV{FCZ$dE8z~Se5GfET5GfET5T-y6&Tg<1VK(qeO?kes z_gMwBHn(SB2TVy{SIxoZ;)=P>=YX9_OsO%q2#`P6 zl)FcD#o-9d8yFLe*YR(Sb`pCDy+)?{sD|5Mcfn=w{OXh0Tzx}{X@L$n4Xc4bp)u?* zQ2mOz4*Q`7GLwazyFAkA3ba8i-Otr@ljBa91!d^M{b%Z@b5{ep*%@#j4&fVuodet9 zEF|GP%paJ?)u8_Mz~`7<4q8)VL36_xb`d;+ zfb}2^UjmEP)!d974PLC@SJwHY5jX1MzhZmg4xEI|Pz!6}BD{syAT6GP#t=W?1eAmF zN+XS_xmyfZLG?AlIZ&TdQ1xdmsh-THId}rL3Hrbv&$mDEy#mdH_QGL!2mbY-{f=LA zwgQfV?pZp01mzJLL-(S7TY#~(2L9IE{gx2B4jw{q%;2%|CLvpWiv0|qAlNV4@de^M zy;Y;zcjzw7w9kW0KBmCf>97x;K|f^6T?oJQJ^V`Un>29Xl+XwZwFflL4d?)Ak_27Pbsqb28=myCNC)nRjW9K`ExZI@6}ElAI@|Es=1lp-1`QXoJul$5YRhw>}=@1J9%;x5SENODkJr*w)taM5U}LF)i2xs1DgCNCF>< jhJVJL<-^~&{t3@=L3yaV&$B5$hTVPm_MhBWhF-q_M7z&N diff --git a/html/app/images/logo.svg b/html/app/images/logo.svg deleted file mode 100644 index 31e11ac..0000000 --- a/html/app/images/logo.svg +++ /dev/null @@ -1,50 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/html/app/index.html b/html/app/index.html deleted file mode 100644 index 6aa9128..0000000 --- a/html/app/index.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - - hyperfox live - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/html/app/scripts/app.js b/html/app/scripts/app.js deleted file mode 100644 index 8e7acad..0000000 --- a/html/app/scripts/app.js +++ /dev/null @@ -1,49 +0,0 @@ -'use strict'; - -/** - * @ngdoc overview - * @name webApp - * @description - * # webApp - * - * Main module of the application. - */ -angular - .module('webApp', [ - 'ngAnimate', - 'ngCookies', - 'ngResource', - 'ngRoute', - 'ngSanitize', - 'ngTouch' - //'luegg.directives' - ]) - .config(function ($routeProvider) { - $routeProvider - .when('/details/:id', { - templateUrl: 'views/details.html', - controller: 'DetailsCtrl' - }) - .when('/:page?', { - templateUrl: 'views/main.html', - controller: 'MainCtrl' - }) - .otherwise({ - redirectTo: '/#/' - }); - }) - .directive('tooltip', function(){ - return { - restrict: 'A', - link: function(scope, element, attrs) { - $(element).hover(function(){ - // on mouseenter - $(element).tooltip('show'); - }, function(){ - // on mouseleave - $(element).tooltip('hide'); - }); - } - }; - }); - ; diff --git a/html/app/scripts/controllers/main.js b/html/app/scripts/controllers/main.js deleted file mode 100644 index 85f3d96..0000000 --- a/html/app/scripts/controllers/main.js +++ /dev/null @@ -1,142 +0,0 @@ -'use strict'; - -var ERR_HYPERFOX_NOT_RUNNING = 'Could not connect to the Hyperfox API. Seems like hyperfox is not running on your local box.'; - -/** - * @ngdoc function - * @name webApp.controller:MainCtrl - * @description - * # MainCtrl - * Controller of the webApp - */ -angular.module('webApp') - .controller('ParentCtrl', function($scope, $routeParams, api) { - - $scope.apierror = null; - - $scope.setTerms = function() { - $scope.$broadcast('search'); - }; - - }) - .controller('DetailsCtrl', function($scope, $routeParams, api) { - $scope.currentID = parseInt($routeParams.id, 10); - $scope.details = {}; - - api.get($scope.currentID).then(function(res) { - $scope.apierror = null; - - $scope.details = res; - }, function(reason) { - $scope.apierror = ERR_HYPERFOX_NOT_RUNNING; - }); - - $scope.$on('search', function() { - location.href = '/#/1'; - refresh(); - }); - - }) - .controller('MainCtrl', function($scope, $routeParams, api) { - - if ($routeParams.source) { - window.localStorage.setItem('source', $routeParams.source); - }; - - $scope.$on('search', function() { - location.href = '/#/'; - refresh(); - }); - - $scope.requests = []; - $scope.totalPages = 0; - $scope.currentPage = parseInt($routeParams.page || 1, 10); - - var pull = function(page, q) { - api.pull(page, q).then(function(res) { - $scope.apierror = null; - - $scope.requests = res.data; - $scope.totalPages = res.pages; - $scope.currentPage = res.page; - - }, function(reason) { - $scope.apierror = ERR_HYPERFOX_NOT_RUNNING; - }); - }; - - var refresh = function() { - pull($scope.currentPage, $scope.q); - }; - - setInterval( - function() { - refresh(); - }, - 10000 - ); - - refresh(); - }) - .filter('mime', function() { - return function(input) { - var c = input.indexOf(';'); - if (c >= 0) { - return input.substr(0, c); - }; - return input; - } - }) - .filter('origin', function() { - return function(input) { - if (input) { - var c = input.indexOf(':'); - if (c >= 0) { - return input.substr(0, c); - }; - } - return input; - } - }) - .filter('size', function() { - return function(input) { - if (!input) { - return '-'; - }; - var kb = 1024; - if (input < kb) { - return input + 'b'; - } else if (input < kb*kb) { - return (input/kb).toFixed(2) + 'Kb'; - } - return (input/(kb*kb)).toFixed(2) + 'Mb'; - } - }) - .filter('time', function() { - return function(input) { - if (input < 1e9) { - return (input/1e6).toFixed(2) + 'ms'; - }; - return (input/1e9).toFixed(2) + 's'; - } - }) - .filter('api_request', function() { - return function(input) { - return endpoint(input); - } - }) - .filter('pageRange', function() { - return function(input, current, total, size) { - var sz = 3; - - var lo = Math.max(1, current - sz); - var hi = Math.min(total, current + sz); - - var i; - for (i = lo; i <= hi; i++) { - input.push(i); - }; - - return input; - }; - }); diff --git a/html/app/scripts/services/main.js b/html/app/scripts/services/main.js deleted file mode 100644 index 8f2b071..0000000 --- a/html/app/scripts/services/main.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict'; - -function endpoint(url) { - var prefix = window.localStorage.getItem('source'); - - if (!prefix) { - prefix = '127.0.0.1:3030'; - }; - - return 'http://' + prefix + url; -} - -var downloadLink = function(id) { - return endpoint('/download?id='+id); -}; - -angular.module('webApp') - .service('api', function($http) { - var api = {}; - - api.get = function(id) { - var req = { - 'method': 'POST', - 'url': endpoint('/get'), - 'data': $.param({ - 'id': id - }), - 'headers': { - 'Content-Type': 'application/x-www-form-urlencoded' - } - }; - - var promise = $http(req).then(function(res) { - return res.data; - }); - - return promise; - }; - - api.pull = function(page, q) { - - var req = { - 'method': 'POST', - 'url': endpoint('/pull'), - 'data': $.param({ - 'page': page, - 'q': q || '' - }), - 'headers': { - 'Content-Type': 'application/x-www-form-urlencoded' - } - }; - - var promise = $http(req).then(function(res) { - return res.data; - }); - - return promise; - }; - - return api; - }); diff --git a/html/app/styles/main.scss b/html/app/styles/main.scss deleted file mode 100644 index 34c40ff..0000000 --- a/html/app/styles/main.scss +++ /dev/null @@ -1,197 +0,0 @@ -$icon-font-path: "../bower_components/bootstrap-sass-official/assets/fonts/bootstrap/"; -// bower:scss -@import "bootstrap-sass-official/assets/stylesheets/_bootstrap.scss"; -// endbower - -.browsehappy { - margin: 0.2em 0; - background: #ccc; - color: #000; - padding: 0.2em 0; -} - -/* Space out content a bit */ -body { - padding-top: 70px; - padding-bottom: 20px; -} - -/* Everything but the jumbotron gets side spacing for mobile first views */ -.header, -.marketing, -.footer { - padding-left: 15px; - padding-right: 15px; -} - -/* Custom page header */ -.header { - border-bottom: 1px solid #e5e5e5; - - /* Make the masthead heading the same height as the navigation */ - h3 { - margin-top: 0; - margin-bottom: 0; - line-height: 40px; - padding-bottom: 19px; - } -} - -/* Custom page footer */ -.footer { - padding-top: 19px; - color: #777; - border-top: 1px solid #e5e5e5; -} - -.container-narrow > hr { - margin: 30px 0; -} - -/* Main marketing message and sign up button */ -.jumbotron { - text-align: center; - border-bottom: 1px solid #e5e5e5; - - .btn { - font-size: 21px; - padding: 14px 24px; - } -} - -/* Supporting marketing content */ -.marketing { - margin: 40px 0; - - p + h4 { - margin-top: 28px; - } -} - -/* Responsive: Portrait tablets and up */ -@media screen and (min-width: 768px) { - .container { - max-width: 730px; - } - - /* Remove the padding we set earlier */ - .header, - .marketing, - .footer { - padding-left: 0; - padding-right: 0; - } - /* Space out the masthead */ - .header { - margin-bottom: 30px; - } - /* Remove the bottom border on the jumbotron for visual effect */ - .jumbotron { - border-bottom: 0; - } -} -#requests-paginator { - margin-left: 10px; - margin-right: 10px; - position: fixed; - bottom: 10px; -} -#requests-paginator ul { - margin: 0px; - padding: 0px; -} -#details-wrapper { - height: auto; -} -#details-wrapper dd { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} -.container { - max-width: 100%; -} -.data-rows { - height: auto; - overflow-y: scroll; - position: fixed; - top: 50px; - left: 0px; - right: 0px; - bottom: 65px; -} -.content-fixed { - position: fixed; - top: 0px; - left: 0px; - bottom: 0px; - right: 0px; -} -.content-fluid { - width: 100%; -} -#requests-wrapper th { - text-align: center; -} - -#requests-wrapper th.th-scheme { - width: 80px; -} -#requests-wrapper th.th-path { - width: 300px; -} -#requests-wrapper th.th-type { - width: 120px; -} -#requests-wrapper th.th-direction { - width: 100px; -} -#requests-wrapper th.th-host { - width: 200px; -} -#requests-wrapper th.th-method { - width: 80px; -} -#requests-wrapper th.th-origin { - width: 120px; -} -#requests-wrapper tbody td { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -#requests-wrapper td.td-path { - max-width: 300px; -} -#requests-wrapper td.td-host { - max-width: 200px; -} -#requests-wrapper td.td-scheme { - text-align: center; -} -#requests-wrapper td.td-type { - max-width: 120px; - text-align: center; -} -#requests-wrapper td.td-origin { - max-width: 150px; -} -#requests-wrapper td.td-method { - text-align: center; -} -#requests-wrapper td.td-status { - text-align: center; -} -#requests-wrapper td.td-size { - text-align: center; -} -#requests-wrapper td.td-actions { - text-align: center; -} -.navbar-brand img { - display: inline; -} -.buttons { - text-align: right; -} diff --git a/html/app/views/details.html b/html/app/views/details.html deleted file mode 100644 index 213b50f..0000000 --- a/html/app/views/details.html +++ /dev/null @@ -1,70 +0,0 @@ -
-
- - - -
- -

{{details.origin | origin}} -> {{details.host}}

- -

Abstract

- -

- On {{details.date_start | date: 'MMM d, y H:mm:ss'}} a - {{details.method}} request was issued to {{details.host}} by - {{details.origin | origin}}. -

-

- The request had a size of {{details.content_length | size}} and took - {{details.time_taken | time}} to complete. -

-

- The request took {{details.time_taken | time}} to complete. -

- -

-
- -
- -
-
-
- - -
-
- -

- - Server response -

- -
- - -
{{header}}
-
{{value}}
-
-
-
- -

- - Client request -

- -
- - -
{{header}}
-
{{value}}
-
-
-
-
- -
-
diff --git a/html/app/views/main.html b/html/app/views/main.html deleted file mode 100644 index 1e2b241..0000000 --- a/html/app/views/main.html +++ /dev/null @@ -1,108 +0,0 @@ - - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
- - - -
-
diff --git a/html/bower.json b/html/bower.json deleted file mode 100644 index f33a5b7..0000000 --- a/html/bower.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "web", - "version": "0.0.0", - "dependencies": { - "angular": "^1.3.0", - "json3": "^3.3.0", - "es5-shim": "^4.0.0", - "bootstrap-sass-official": "^3.2.0", - "angular-animate": "^1.3.0", - "angular-cookies": "^1.3.0", - "angular-resource": "^1.3.0", - "angular-route": "^1.3.0", - "angular-sanitize": "^1.3.0", - "angular-touch": "^1.3.0", - "angularjs-scroll-glue-Luegg": "~2.0.3" - }, - "devDependencies": { - "angular-mocks": "~1.3.0", - "angular-scenario": "~1.3.0" - }, - "appPath": "app" -} diff --git a/html/package.json b/html/package.json deleted file mode 100644 index 03d9e6b..0000000 --- a/html/package.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "web", - "version": "0.0.0", - "dependencies": { - "grunt": "~0.4.5" - }, - "devDependencies": { - "grunt": "^0.4.1", - "grunt-autoprefixer": "^0.7.3", - "grunt-concurrent": "^0.5.0", - "grunt-contrib-clean": "^0.5.0", - "grunt-contrib-compass": "~1.0.1", - "grunt-contrib-concat": "^0.4.0", - "grunt-contrib-connect": "^0.7.1", - "grunt-contrib-copy": "^0.5.0", - "grunt-contrib-cssmin": "^0.9.0", - "grunt-contrib-htmlmin": "^0.3.0", - "grunt-contrib-imagemin": "^0.8.1", - "grunt-contrib-jshint": "^0.10.0", - "grunt-contrib-uglify": "^0.4.0", - "grunt-contrib-watch": "^0.6.1", - "grunt-filerev": "^0.2.1", - "grunt-google-cdn": "^0.4.0", - "grunt-karma": "^0.9.0", - "grunt-newer": "^0.7.0", - "grunt-ng-annotate": "^0.4.0", - "grunt-svgmin": "^0.4.0", - "grunt-usemin": "^2.1.1", - "grunt-wiredep": "^1.7.0", - "jasmine-core": "^2.1.3", - "jshint-stylish": "^0.2.0", - "karma": "^0.12.28", - "karma-jasmine": "^0.3.2", - "karma-phantomjs-launcher": "^0.1.4", - "load-grunt-tasks": "^0.4.0", - "time-grunt": "^0.3.1" - }, - "engines": { - "node": ">=0.10.0" - }, - "scripts": { - "test": "grunt test" - } -} diff --git a/html/test/.jshintrc b/html/test/.jshintrc deleted file mode 100644 index b1be025..0000000 --- a/html/test/.jshintrc +++ /dev/null @@ -1,36 +0,0 @@ -{ - "node": true, - "browser": true, - "esnext": true, - "bitwise": true, - "camelcase": true, - "curly": true, - "eqeqeq": true, - "immed": true, - "indent": 2, - "latedef": true, - "newcap": true, - "noarg": true, - "quotmark": "single", - "regexp": true, - "undef": true, - "unused": true, - "strict": true, - "trailing": true, - "smarttabs": true, - "globals": { - "after": false, - "afterEach": false, - "angular": false, - "before": false, - "beforeEach": false, - "browser": false, - "describe": false, - "expect": false, - "inject": false, - "it": false, - "jasmine": false, - "spyOn": false - } -} - diff --git a/html/test/karma.conf.js b/html/test/karma.conf.js deleted file mode 100644 index 5242282..0000000 --- a/html/test/karma.conf.js +++ /dev/null @@ -1,75 +0,0 @@ -// Karma configuration -// http://karma-runner.github.io/0.12/config/configuration-file.html -// Generated on 2014-12-20 using -// generator-karma 0.8.3 - -module.exports = function(config) { - 'use strict'; - - config.set({ - // enable / disable watching file and executing tests whenever any file changes - autoWatch: true, - - // base path, that will be used to resolve files and exclude - basePath: '../', - - // testing framework to use (jasmine/mocha/qunit/...) - frameworks: ['jasmine'], - - // list of files / patterns to load in the browser - files: [ - 'bower_components/angular/angular.js', - 'bower_components/angular-mocks/angular-mocks.js', - 'bower_components/angular-animate/angular-animate.js', - 'bower_components/angular-cookies/angular-cookies.js', - 'bower_components/angular-resource/angular-resource.js', - 'bower_components/angular-route/angular-route.js', - 'bower_components/angular-sanitize/angular-sanitize.js', - 'bower_components/angular-touch/angular-touch.js', - 'app/scripts/**/*.js', - 'test/mock/**/*.js', - 'test/spec/**/*.js' - ], - - // list of files / patterns to exclude - exclude: [], - - // web server port - port: 8080, - - // Start these browsers, currently available: - // - Chrome - // - ChromeCanary - // - Firefox - // - Opera - // - Safari (only Mac) - // - PhantomJS - // - IE (only Windows) - browsers: [ - 'PhantomJS' - ], - - // Which plugins to enable - plugins: [ - 'karma-phantomjs-launcher', - 'karma-jasmine' - ], - - // Continuous Integration mode - // if true, it capture browsers, run tests and exit - singleRun: false, - - colors: true, - - // level of logging - // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG - logLevel: config.LOG_INFO, - - // Uncomment the following lines if you are using grunt's server to run the tests - // proxies: { - // '/': 'http://localhost:9000/' - // }, - // URL root prevent conflicts with the site root - // urlRoot: '_karma_' - }); -}; diff --git a/html/test/spec/controllers/about.js b/html/test/spec/controllers/about.js deleted file mode 100644 index 2366696..0000000 --- a/html/test/spec/controllers/about.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -describe('Controller: AboutCtrl', function () { - - // load the controller's module - beforeEach(module('webApp')); - - var AboutCtrl, - scope; - - // Initialize the controller and a mock scope - beforeEach(inject(function ($controller, $rootScope) { - scope = $rootScope.$new(); - AboutCtrl = $controller('AboutCtrl', { - $scope: scope - }); - })); - - it('should attach a list of awesomeThings to the scope', function () { - expect(scope.awesomeThings.length).toBe(3); - }); -}); diff --git a/html/test/spec/controllers/main.js b/html/test/spec/controllers/main.js deleted file mode 100644 index 482025b..0000000 --- a/html/test/spec/controllers/main.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -describe('Controller: MainCtrl', function () { - - // load the controller's module - beforeEach(module('webApp')); - - var MainCtrl, - scope; - - // Initialize the controller and a mock scope - beforeEach(inject(function ($controller, $rootScope) { - scope = $rootScope.$new(); - MainCtrl = $controller('MainCtrl', { - $scope: scope - }); - })); - - it('should attach a list of awesomeThings to the scope', function () { - expect(scope.awesomeThings.length).toBe(3); - }); -}); From 601b9475f11a5170f1f1b540eff498865b4c2c42 Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Fri, 10 Jun 2016 22:32:00 -0500 Subject: [PATCH 03/34] Git and editor config files --- .editorconfig | 7 ++++ .gitattributes | 106 +++++++++++++++++++++++++++++++++++++++++++++++++ .gitignore | 10 +++++ 3 files changed, 123 insertions(+) create mode 100755 .editorconfig create mode 100755 .gitattributes create mode 100755 .gitignore diff --git a/.editorconfig b/.editorconfig new file mode 100755 index 0000000..d4eed84 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,7 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = false +indent_style = space +indent_size = 2 diff --git a/.gitattributes b/.gitattributes new file mode 100755 index 0000000..a29125a --- /dev/null +++ b/.gitattributes @@ -0,0 +1,106 @@ +# From https://github.com/Danimoth/gitattributes/blob/master/Web.gitattributes + +# Handle line endings automatically for files detected as text +# and leave all files detected as binary untouched. +* text=auto + +# +# The above will handle all files NOT found below +# + +# +## These files are text and should be normalized (Convert crlf => lf) +# + +# source code +*.php text +*.css text +*.sass text +*.scss text +*.less text +*.styl text +*.js text eol=lf +*.coffee text +*.json text +*.htm text +*.html text +*.xml text +*.svg text +*.txt text +*.ini text +*.inc text +*.pl text +*.rb text +*.py text +*.scm text +*.sql text +*.sh text +*.bat text + +# templates +*.ejs text +*.hbt text +*.jade text +*.haml text +*.hbs text +*.dot text +*.tmpl text +*.phtml text + +# server config +.htaccess text + +# git config +.gitattributes text +.gitignore text +.gitconfig text + +# code analysis config +.jshintrc text +.jscsrc text +.jshintignore text +.csslintrc text + +# misc config +*.yaml text +*.yml text +.editorconfig text + +# build config +*.npmignore text +*.bowerrc text + +# Heroku +Procfile text +.slugignore text + +# Documentation +*.md text +LICENSE text +AUTHORS text + + +# +## These files are binary and should be left untouched +# + +# (binary is a macro for -text -diff) +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.mov binary +*.mp4 binary +*.mp3 binary +*.flv binary +*.fla binary +*.swf binary +*.gz binary +*.zip binary +*.7z binary +*.ttf binary +*.eot binary +*.woff binary +*.pyc binary +*.pdf binary diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..5d06c05 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +# Don't check auto-generated stuff into git +coverage +build +node_modules +stats.json + +# Cruft +.DS_Store +npm-debug.log +.idea From 8549072e883b7a2500d79dff60ab9ae1cee418fd Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Fri, 10 Jun 2016 22:32:00 -0500 Subject: [PATCH 04/34] Blank React App with sagas and reducers --- app/app.js | 59 ++++++++++++++++ app/containers/App/index.js | 20 ++++++ app/containers/App/selectors.js | 18 +++++ app/containers/App/tests/selectors.test.js | 14 ++++ app/containers/HomePage/index.js | 14 ++++ app/containers/NotFoundPage/index.js | 14 ++++ app/index.html | 13 ++++ app/reducers.js | 45 ++++++++++++ app/routes.js | 41 +++++++++++ app/store.js | 49 +++++++++++++ app/store.test.js | 25 +++++++ app/tests/store.test.js | 25 +++++++ app/utils/hooks.js | 22 ++++++ app/utils/tests/hooks.test.js | 82 ++++++++++++++++++++++ 14 files changed, 441 insertions(+) create mode 100755 app/app.js create mode 100755 app/containers/App/index.js create mode 100755 app/containers/App/selectors.js create mode 100755 app/containers/App/tests/selectors.test.js create mode 100755 app/containers/HomePage/index.js create mode 100755 app/containers/NotFoundPage/index.js create mode 100755 app/index.html create mode 100755 app/reducers.js create mode 100755 app/routes.js create mode 100755 app/store.js create mode 100755 app/store.test.js create mode 100755 app/tests/store.test.js create mode 100755 app/utils/hooks.js create mode 100755 app/utils/tests/hooks.test.js diff --git a/app/app.js b/app/app.js new file mode 100755 index 0000000..e1573ab --- /dev/null +++ b/app/app.js @@ -0,0 +1,59 @@ +/** +app.js +This is the entry file for the application, only setup and boilerplate code. +**/ + +import 'babel-polyfill' + +// Load the manifest.json file and the .htaccess file +import 'file?name=[name].[ext]!./manifest.json' + +// Import all the third party stuff +import React from 'react' +import ReactDOM from 'react-dom' +import { Provider } from 'react-redux' +import { applyRouterMiddleware, Router, browserHistory } from 'react-router' +import { syncHistoryWithStore } from 'react-router-redux' +import useScroll from 'react-router-scroll' +import configureStore from './store' + +// Import the CSS reset, which HtmlWebpackPlugin transfers to the build folder +import 'sanitize.css/lib/sanitize.css' + +// Create redux store with history +// this uses the singleton browserHistory provided by react-router +// Optionally, this could be changed to leverage a created history +// e.g. `const browserHistory = useRouterHistory(createBrowserHistory)();` +const initialState = {} +const store = configureStore(initialState, browserHistory) + +// Sync history and store, as the react-router-redux reducer +// is under the non-default key ("routing"), selectLocationState +// must be provided for resolving how to retrieve the "route" in the state +import { selectLocationState } from 'containers/App/selectors' +const history = syncHistoryWithStore(browserHistory, store, { + selectLocationState: selectLocationState() +}) + +// Set up the router, wrapping all Routes in the App component +import App from 'containers/App' +import createRoutes from './routes' +const rootRoute = { + component: App, + childRoutes: createRoutes(store) +} + +ReactDOM.render( + + + , + document.getElementById('app') +) + +// Install ServiceWorker and AppCache in the end since +// it's not most important operation and if main code fails, +// we do not want it installed +import { install } from 'offline-plugin/runtime' +install() diff --git a/app/containers/App/index.js b/app/containers/App/index.js new file mode 100755 index 0000000..e578c4f --- /dev/null +++ b/app/containers/App/index.js @@ -0,0 +1,20 @@ +/* App.react.js + * This component is the skeleton around the actual pages, and should only + * contain code that should be seen on all pages. (e.g. navigation bar) + */ + +import React from 'react' + +export default class App extends React.Component { + static propTypes = { + children: React.PropTypes.node + } + + render () { + return ( +
+ {this.props.children} +
+ ) + } +} diff --git a/app/containers/App/selectors.js b/app/containers/App/selectors.js new file mode 100755 index 0000000..e2f8108 --- /dev/null +++ b/app/containers/App/selectors.js @@ -0,0 +1,18 @@ +// selectLocationState expects a plain JS object for the routing state +const selectLocationState = () => { + let prevRoutingState + let prevRoutingStateJS + + return (state) => { + const routingState = state.get('route') // or state.route + + if (!routingState.equals(prevRoutingState)) { + prevRoutingState = routingState + prevRoutingStateJS = routingState.toJS() + } + + return prevRoutingStateJS + } +} + +export {selectLocationState} diff --git a/app/containers/App/tests/selectors.test.js b/app/containers/App/tests/selectors.test.js new file mode 100755 index 0000000..8f43037 --- /dev/null +++ b/app/containers/App/tests/selectors.test.js @@ -0,0 +1,14 @@ +import { fromJS } from 'immutable' +import expect from 'expect' + +import { selectLocationState } from 'containers/App/selectors' + +describe('selectLocationState', () => { + it('should select the route as a plain JS object', () => { + const route = fromJS({ + locationBeforeTransitions: null + }) + const mockedState = fromJS({route}) + expect(selectLocationState()(mockedState)).toEqual(route.toJS()) + }) +}) diff --git a/app/containers/HomePage/index.js b/app/containers/HomePage/index.js new file mode 100755 index 0000000..ca2acf1 --- /dev/null +++ b/app/containers/HomePage/index.js @@ -0,0 +1,14 @@ +/* HomePage + * This is the first thing users see of our App, at the '/' route + */ + +import React from 'react' + +export default class HomePage extends React.Component { + + render () { + return ( +

Hyperfox!

+ ) + } +} diff --git a/app/containers/NotFoundPage/index.js b/app/containers/NotFoundPage/index.js new file mode 100755 index 0000000..84ca606 --- /dev/null +++ b/app/containers/NotFoundPage/index.js @@ -0,0 +1,14 @@ +/* NotFoundPage + * This is the page we show when the user visits a url that doesn't have a route + */ + +import React from 'react' + +export default class NotFound extends React.Component { + + render () { + return ( +

Page Not Found

+ ) + } +} diff --git a/app/index.html b/app/index.html new file mode 100755 index 0000000..a50e1ec --- /dev/null +++ b/app/index.html @@ -0,0 +1,13 @@ + + + + + + + + Hyperfox + + +
+ + diff --git a/app/reducers.js b/app/reducers.js new file mode 100755 index 0000000..727a7b5 --- /dev/null +++ b/app/reducers.js @@ -0,0 +1,45 @@ +/* Combine all reducers in this file and export the combined reducers. + * If we were to do this in store.js, reducers wouldn't be hot reloadable. + */ + +import { combineReducers } from 'redux-immutable' +import { fromJS } from 'immutable' +import { LOCATION_CHANGE } from 'react-router-redux' + +/* + * routeReducer + * + * The reducer merges route location changes into our immutable state. + * The change is necessitated by moving to react-router-redux@4 + * + */ + +// Initial routing state +const routeInitialState = fromJS({ + locationBeforeTransitions: null +}) + +/** + * Merge route into the global application state + */ +function routeReducer (state = routeInitialState, action) { + switch (action.type) { + /* istanbul ignore next */ + case LOCATION_CHANGE: + return state.merge({ + locationBeforeTransitions: action.payload + }) + default: + return state + } +} + +/** + * Creates the main reducer with the asynchronously loaded ones + */ +export default function createReducer (asyncReducers) { + return combineReducers({ + route: routeReducer, + ...asyncReducers + }) +} diff --git a/app/routes.js b/app/routes.js new file mode 100755 index 0000000..b9e9c48 --- /dev/null +++ b/app/routes.js @@ -0,0 +1,41 @@ +// import { getHooks } from 'utils/hooks' + +const errorLoading = (err) => { + console.error('Dynamic page loading failed', err) +} + +const loadModule = (cb) => (componentModule) => { + cb(null, componentModule.default) +} + +export default function createRoutes () { + // const { injectReducer, injectSagas } = getHooks(store) + + return [ + { + path: '/', + name: 'home', + getComponent (nextState, cb) { + const importModules = Promise.all([ + System.import('containers/HomePage') + ]) + + const renderRoute = loadModule(cb) + + importModules.then(([component]) => { + renderRoute(component) + }) + + importModules.catch(errorLoading) + } + }, { + path: '*', + name: 'notfound', + getComponent (nextState, cb) { + System.import('containers/NotFoundPage') + .then(loadModule(cb)) + .catch(errorLoading) + } + } + ] +} diff --git a/app/store.js b/app/store.js new file mode 100755 index 0000000..d1e20af --- /dev/null +++ b/app/store.js @@ -0,0 +1,49 @@ +/* Create the store with asynchronously loaded reducers */ + +import { createStore, applyMiddleware, compose } from 'redux' +import { fromJS } from 'immutable' +import { routerMiddleware } from 'react-router-redux' +import createSagaMiddleware from 'redux-saga' +import createReducer from './reducers' + +const sagaMiddleware = createSagaMiddleware() +const devtools = window.devToolsExtension || (() => noop => noop) + +export default function configureStore (initialState = {}, history) { + // Create the store with two middlewares + // 1. sagaMiddleware: Makes redux-sagas work + // 2. routerMiddleware: Syncs the location/URL path to the state + const middlewares = [ + sagaMiddleware, + routerMiddleware(history) + ] + + const enhancers = [ + applyMiddleware(...middlewares), + devtools() + ] + + const store = createStore( + createReducer(), + fromJS(initialState), + compose(...enhancers) + ) + + // Create hook for async sagas + store.runSaga = sagaMiddleware.run + + // Make reducers hot reloadable + /* istanbul ignore next */ + if (module.hot) { + System.import('./reducers').then((reducerModule) => { + const createReducers = reducerModule.default + const nextReducers = createReducers(store.asyncReducers) + + store.replaceReducer(nextReducers) + }) + } + + // Initialize it with no other reducers + store.asyncReducers = {} + return store +} diff --git a/app/store.test.js b/app/store.test.js new file mode 100755 index 0000000..bb7c2a4 --- /dev/null +++ b/app/store.test.js @@ -0,0 +1,25 @@ +/* Test store addons */ + +import expect from 'expect' +import configureStore from './store' +import { browserHistory } from 'react-router' + +describe('configureStore', () => { + let store + + before(() => { + store = configureStore({}, browserHistory) + }) + + describe('asyncReducers', () => { + it('should contain an object for async reducers', () => { + expect(typeof store.asyncReducers).toEqual('object') + }) + }) + + describe('runSaga', () => { + it('should contain a hook for `sagaMiddleware.run`', () => { + expect(typeof store.runSaga).toEqual('function') + }) + }) +}) diff --git a/app/tests/store.test.js b/app/tests/store.test.js new file mode 100755 index 0000000..2d9c2f9 --- /dev/null +++ b/app/tests/store.test.js @@ -0,0 +1,25 @@ +/* Test store addons */ + +import expect from 'expect' +import configureStore from '../store' +import { browserHistory } from 'react-router' + +describe('configureStore', () => { + let store + + before(() => { + store = configureStore({}, browserHistory) + }) + + describe('asyncReducers', () => { + it('should contain an object for async reducers', () => { + expect(typeof store.asyncReducers).toEqual('object') + }) + }) + + describe('runSaga', () => { + it('should contain a hook for `sagaMiddleware.run`', () => { + expect(typeof store.runSaga).toEqual('function') + }) + }) +}) diff --git a/app/utils/hooks.js b/app/utils/hooks.js new file mode 100755 index 0000000..f2789b5 --- /dev/null +++ b/app/utils/hooks.js @@ -0,0 +1,22 @@ +import createReducer from 'reducers.js' + +/* Inject an asynchronously loaded reducer */ +export function injectAsyncReducer (store) { + return (name, asyncReducer) => { + store.asyncReducers[name] = asyncReducer + store.replaceReducer(createReducer(store.asyncReducers)) + } +} + +/* Inject an asynchronously loaded saga */ +export function injectAsyncSagas (store) { + return (sagas) => sagas.map(store.runSaga) +} + +/* Helper for creating injectors */ +export function getHooks (store) { + return { + injectReducer: injectAsyncReducer(store), + injectSagas: injectAsyncSagas(store) + } +} diff --git a/app/utils/tests/hooks.test.js b/app/utils/tests/hooks.test.js new file mode 100755 index 0000000..4f0a1c7 --- /dev/null +++ b/app/utils/tests/hooks.test.js @@ -0,0 +1,82 @@ +/* Test hooks */ + +import expect from 'expect' +import configureStore from 'store.js' +import { memoryHistory } from 'react-router' +import { put } from 'redux-saga/effects' +import { fromJS } from 'immutable' + +import {injectAsyncReducer, injectAsyncSagas, getHooks} from 'utils/hooks' + +// Fixtures + +const initialState = fromJS({ reduced: 'soon' }) + +const reducer = (state = initialState, action) => { + switch (action.type) { + case 'TEST': + return state.set('reduced', action.payload) + default: + return state + } +} + +const sagas = [ + function * testSaga () { + yield put({ type: 'TEST', payload: 'yup' }) + } +] + +describe('hooks', () => { + let store + + describe('getHooks', () => { + before(() => { + store = configureStore({}, memoryHistory) + }) + + it('given a store, should return all hooks', () => { + const { injectReducer, injectSagas } = getHooks(store) + + injectReducer('test', reducer) + injectSagas(sagas) + + const actual = store.getState().get('test') + const expected = initialState.merge({ reduced: 'yup' }) + + expect(actual.toJS()).toEqual(expected.toJS()) + }) + }) + + describe('helpers', () => { + before(() => { + store = configureStore({}, memoryHistory) + }) + + describe('injectAsyncReducer', () => { + it('given a store, it should provide a function to inject a reducer', () => { + const injectReducer = injectAsyncReducer(store) + + injectReducer('test', reducer) + + const actual = store.getState().get('test') + const expected = initialState + + expect(actual.toJS()).toEqual(expected.toJS()) + }) + }) + + describe('injectAsyncSagas', () => { + it('given a store, it should provide a function to inject a saga', () => { + const injectSagas = injectAsyncSagas(store) + + injectSagas(sagas) + + const actual = store.getState().get('test') + const expected = initialState.merge({ reduced: 'yup' }) + + expect(actual.toJS()).toEqual(expected.toJS()) + }) + }) + }) +}) From 69eece7cc1cf7920e6d77b37edcc16dc3e4860a2 Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Fri, 10 Jun 2016 22:32:00 -0500 Subject: [PATCH 05/34] Add standard linter config to package.json --- package.json | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 package.json diff --git a/package.json b/package.json new file mode 100644 index 0000000..3b96dde --- /dev/null +++ b/package.json @@ -0,0 +1,158 @@ +{ + "name": "hyperfox-live", + "version": "2.0.0", + "description": "", + "repository": { + "type": "git", + "url": "git://github.com/xiam/hyperfox-live.git" + }, + "engines": { + "npm": ">=3" + }, + "scripts": { + "postinstall": "npm run build:dll", + "prebuild": "npm run test && npm run build:clean", + "build": "cross-env NODE_ENV=production webpack --config internals/webpack/webpack.prod.babel.js --color -p", + "build:clean": "rimraf ./build/*", + "build:dll": "node ./internals/scripts/dependencies.js", + "start": "cross-env NODE_ENV=development node server", + "start:production": "npm run build && npm run start:prod", + "start:prod": "cross-env NODE_ENV=production node server", + "test": "cross-env NODE_ENV=test karma start internals/testing/karma.conf.js --single-run", + "test:watch": "npm run test -- --auto-watch --no-single-run", + "test:firefox": "npm run test -- --browsers Firefox", + "test:safari": "npm run test -- --browsers Safari", + "test:ie": "npm run test -- --browsers IE", + "coveralls": "cat ./coverage/lcov/lcov.info | coveralls" + }, + "babel": { + "presets": [ + "es2015-webpack", + "react", + "stage-0" + ], + "env": { + "production": { + "only": [ + "app" + ], + "plugins": [ + "transform-react-remove-prop-types", + "transform-react-constant-elements", + "transform-react-inline-elements" + ] + } + } + }, + "dllPlugin": { + "path": "node_modules/hyperfox-dlls", + "exclude": [ + "chalk", + "compression", + "cross-env", + "express", + "minimist", + "sanitize.css" + ], + "include": [ + "core-js", + "lodash", + "eventsource-polyfill" + ] + }, + "dependencies": { + "babel-polyfill": "^6.7.4", + "chalk": "^1.1.3", + "compression": "^1.6.1", + "express": "^4.13.4", + "fontfaceobserver": "^1.7.1", + "history": "^2.1.0", + "immutable": "^3.8.1", + "minimist": "^1.2.0", + "react": "^15.0.1", + "react-dom": "^15.0.1", + "react-redux": "^4.4.5", + "react-router": "^2.3.0", + "react-router-redux": "^4.0.4", + "react-router-scroll": "^0.2.0", + "redux": "^3.5.2", + "redux-immutable": "^3.0.6", + "redux-saga": "^0.10.0", + "reselect": "^2.5.1", + "sanitize.css": "^3.3.0", + "whatwg-fetch": "^1.0.0" + }, + "devDependencies": { + "babel-core": "^6.7.7", + "babel-eslint": "^6.0.5", + "babel-loader": "^6.2.4", + "babel-plugin-react-transform": "^2.0.2", + "babel-plugin-transform-react-constant-elements": "^6.8.0", + "babel-plugin-transform-react-inline-elements": "^6.8.0", + "babel-plugin-transform-react-remove-prop-types": "^0.2.7", + "babel-preset-es2015": "^6.6.0", + "babel-preset-es2015-webpack": "^6.4.1", + "babel-preset-react": "^6.5.0", + "babel-preset-react-hmre": "^1.1.1", + "babel-preset-stage-0": "^6.5.0", + "chai": "^3.5.0", + "chai-enzyme": "^0.4.2", + "cheerio": "^0.20.0", + "coveralls": "^2.11.9", + "cross-env": "^1.0.7", + "css-loader": "^0.23.1", + "enzyme": "^2.2.0", + "eventsource-polyfill": "^0.9.6", + "expect": "^1.18.0", + "expect-jsx": "^2.5.1", + "exports-loader": "^0.6.3", + "extract-text-webpack-plugin": "^1.0.1", + "file-loader": "^0.8.5", + "html-loader": "^0.4.3", + "html-webpack-plugin": "^2.16.0", + "image-webpack-loader": "^1.8.0", + "imports-loader": "^0.6.5", + "isparta": "^4.0.0", + "isparta-loader": "^2.0.0", + "json-loader": "^0.5.4", + "karma": "^0.13.22", + "karma-chrome-launcher": "^1.0.1", + "karma-coverage": "^1.0.0", + "karma-firefox-launcher": "^1.0.0", + "karma-ie-launcher": "^1.0.0", + "karma-mocha": "^1.0.1", + "karma-mocha-reporter": "^2.0.3", + "karma-safari-launcher": "^1.0.0", + "karma-sourcemap-loader": "^0.3.7", + "karma-webpack": "^1.7.0", + "lodash": "^4.13.1", + "minimist": "^1.2.0", + "mocha": "^2.4.5", + "null-loader": "^0.1.1", + "offline-plugin": "^3.2.0", + "postcss-cssnext": "^2.5.2", + "postcss-focus": "^1.0.0", + "postcss-loader": "^0.9.1", + "postcss-reporter": "^1.3.3", + "rimraf": "^2.5.2", + "shelljs": "^0.7.0", + "sinon": "^2.0.0-pre", + "style-loader": "^0.13.1", + "url-loader": "^0.5.7", + "webpack": "2.1.0-beta.13", + "webpack-dev-middleware": "^1.6.1", + "webpack-hot-middleware": "^2.10.0" + }, + "standard": { + "parser": "babel-eslint", + "globals": [ + "describe", + "it", + "fetch", + "before", + "beforeEach", + "afterEach", + "Response" + ] + } +} From eeeb6477c8901bc8b8c5e11e3bdb5d06ff4ef182 Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Sat, 11 Jun 2016 22:32:00 -0500 Subject: [PATCH 06/34] Webpack config files with DLL plugin and karma testing --- internals/config.js | 55 +++++++++ internals/scripts/dependencies.js | 49 ++++++++ internals/testing/karma.conf.js | 58 ++++++++++ internals/testing/test-bundler.js | 12 ++ internals/webpack/webpack.base.babel.js | 85 ++++++++++++++ internals/webpack/webpack.dev.babel.js | 142 ++++++++++++++++++++++++ internals/webpack/webpack.dll.babel.js | 34 ++++++ internals/webpack/webpack.prod.babel.js | 108 ++++++++++++++++++ internals/webpack/webpack.test.babel.js | 88 +++++++++++++++ 9 files changed, 631 insertions(+) create mode 100755 internals/config.js create mode 100755 internals/scripts/dependencies.js create mode 100755 internals/testing/karma.conf.js create mode 100755 internals/testing/test-bundler.js create mode 100755 internals/webpack/webpack.base.babel.js create mode 100755 internals/webpack/webpack.dev.babel.js create mode 100755 internals/webpack/webpack.dll.babel.js create mode 100755 internals/webpack/webpack.prod.babel.js create mode 100755 internals/webpack/webpack.test.babel.js diff --git a/internals/config.js b/internals/config.js new file mode 100755 index 0000000..87ae811 --- /dev/null +++ b/internals/config.js @@ -0,0 +1,55 @@ +const resolve = require('path').resolve +const pullAll = require('lodash/pullAll') +const uniq = require('lodash/uniq') + +const HyperfoxLive = { + // This refers to the hyperfox-live version this project is based on. + version: '2.0.0', + + /** + * The DLL Plugin provides a dramatic speed increase to webpack build and hot module reloading + * by caching the module metadata for all of our npm dependencies. We enable it by default + * in development. + * + * + * To disable the DLL Plugin, set this value to false. + */ + dllPlugin: { + defaults: { + /** + * we need to exclude dependencies which are not intended for the browser + * by listing them here. + */ + exclude: [ + 'chalk', + 'compression', + 'cross-env', + 'express', + 'minimist', + 'sanitize.css' + ], + + /** + * Specify any additional dependencies here. We include core-js and lodash + * since a lot of our dependencies depend on them and they get picked up by webpack. + */ + include: ['core-js', 'eventsource-polyfill', 'babel-polyfill', 'lodash'], + + // The path where the DLL manifest and bundle will get built + path: resolve('../node_modules/hyperfox-dlls') + }, + + entry (pkg) { + const dependencyNames = Object.keys(pkg.dependencies) + const exclude = pkg.dllPlugin.exclude || HyperfoxLive.dllPlugin.defaults.exclude + const include = pkg.dllPlugin.include || HyperfoxLive.dllPlugin.defaults.include + const includeDependencies = uniq(dependencyNames.concat(include)) + + return { + hyperfoxLiveDeps: pullAll(includeDependencies, exclude) + } + } + } +} + +module.exports = HyperfoxLive diff --git a/internals/scripts/dependencies.js b/internals/scripts/dependencies.js new file mode 100755 index 0000000..50b62a5 --- /dev/null +++ b/internals/scripts/dependencies.js @@ -0,0 +1,49 @@ +/*eslint-disable*/ + +// No need to build the DLL in production +if (process.env.NODE_ENV === 'production') { + process.exit(0) +} + +require('shelljs/global') + +const path = require('path') +const fs = require('fs') +const exists = fs.existsSync +const writeFile = fs.writeFileSync + +const defaults = require('lodash/defaultsDeep') +const pkg = require(path.join(process.cwd(), 'package.json')) +const config = require('../config') +const dllConfig = defaults(pkg.dllPlugin, config.dllPlugin.defaults) +const outputPath = path.join(process.cwd(), dllConfig.path) +const dllManifestPath = path.join(outputPath, 'package.json') + +/** + * I use node_modules/hyperfox-dlls by default just because + * it isn't going to be version controlled and babel wont try to parse it. + */ +mkdir('-p', outputPath) + +echo('Building the Webpack DLL...') + +/** + * Create a manifest so npm install doesnt warn us + */ +if (!exists(dllManifestPath)) { + writeFile( + dllManifestPath, + JSON.stringify(defaults({ + name: 'hyperfox-dlls', + private: true, + author: pkg.author, + repository: pkg.repository, + version: pkg.version + }), null, 2), + + 'utf8' + ) +} + +// the BUILDING_DLL env var is set to avoid confusing the development environment +exec('cross-env BUILDING_DLL=true webpack --display-chunks --color --config internals/webpack/webpack.dll.babel.js') diff --git a/internals/testing/karma.conf.js b/internals/testing/karma.conf.js new file mode 100755 index 0000000..caeb989 --- /dev/null +++ b/internals/testing/karma.conf.js @@ -0,0 +1,58 @@ +const webpackConfig = require('../webpack/webpack.test.babel') +const argv = require('minimist')(process.argv.slice(2)) +const path = require('path') + +module.exports = (config) => { + config.set({ + frameworks: ['mocha'], + reporters: ['coverage', 'mocha'], + browsers: process.env.TRAVIS ? ['ChromeTravis'] : process.env.APPVEYOR ? ['IE'] : ['Chrome'], + + autoWatch: false, + singleRun: true, + + client: { + mocha: { + grep: argv.grep + } + }, + + files: [ + { + pattern: './test-bundler.js', + watched: false, + served: true, + included: true + } + ], + + preprocessors: { + ['./test-bundler.js']: ['webpack', 'sourcemap'] + }, + + webpack: webpackConfig, + + // make Webpack bundle generation quiet + webpackMiddleware: { + noInfo: true, + stats: 'errors-only' + }, + + customLaunchers: { + ChromeTravis: { + base: 'Chrome', + flags: ['--no-sandbox'] + } + }, + + coverageReporter: { + dir: path.join(process.cwd(), 'coverage'), + reporters: [ + { type: 'lcov', subdir: 'lcov' }, + { type: 'html', subdir: 'html' }, + { type: 'text-summary' } + ] + } + + }) +} diff --git a/internals/testing/test-bundler.js b/internals/testing/test-bundler.js new file mode 100755 index 0000000..2471ed7 --- /dev/null +++ b/internals/testing/test-bundler.js @@ -0,0 +1,12 @@ +// needed for regenerator-runtime +// (ES7 generator support is required by redux-saga) +import 'babel-polyfill' + +import chai from 'chai' +import chaiEnzyme from 'chai-enzyme' +chai.use(chaiEnzyme()) + +// Include all .js files under `app`, except app.js, reducers.js, routes.js and +// store.js. This is for isparta code coverage +const context = require.context('../../app', true, /^^((?!(app|reducers|routes|store)).)*\.js$/) +context.keys().forEach(context) diff --git a/internals/webpack/webpack.base.babel.js b/internals/webpack/webpack.base.babel.js new file mode 100755 index 0000000..cec3896 --- /dev/null +++ b/internals/webpack/webpack.base.babel.js @@ -0,0 +1,85 @@ +/* COMMON WEBPACK CONFIGURATION */ + +const path = require('path') +const webpack = require('webpack') + +module.exports = (options) => ({ + entry: options.entry, + output: Object.assign({ // Compile into js/build.js + path: path.resolve(process.cwd(), 'build'), + publicPath: '/' + }, options.output), // Merge with env dependent settings + module: { + loaders: [{ + test: /\.js$/, // Transform all .js files required somewhere with Babel + loader: 'babel', + exclude: /node_modules/, + query: options.babelQuery + }, { + // Transform our own .css files with PostCSS and CSS-modules + test: /\.css$/, + exclude: /node_modules/, + loader: options.cssLoaders + }, { + // Do not transform vendor's CSS with CSS-modules + // The point is that they remain in global scope. + // Since we require these CSS files in our JS or CSS files, + // they will be a part of our compilation either way. + // So, no need for ExtractTextPlugin here. + test: /\.css$/, + include: /node_modules/, + loaders: ['style-loader', 'css-loader'] + }, { + test: /\.(eot|svg|ttf|woff|woff2)$/, + loader: 'file-loader' + }, { + test: /\.(jpg|png|gif)$/, + loaders: [ + 'file-loader', + 'image-webpack?{progressive:true, optimizationLevel: 7, interlaced: false, pngquant:{quality: "65-90", speed: 4}}' + ] + }, { + test: /\.html$/, + loader: 'html-loader' + }, { + test: /\.json$/, + loader: 'json-loader' + }, { + test: /\.(mp4|webm)$/, + loader: 'url-loader?limit=10000' + }] + }, + plugins: options.plugins.concat([ + new webpack.ProvidePlugin({ + // make fetch available + fetch: 'exports?self.fetch!whatwg-fetch' + }), + + // Always expose NODE_ENV to webpack, in order to use `process.env.NODE_ENV` + // inside your code for any environment checks; UglifyJS will automatically + // drop any unreachable code. + new webpack.DefinePlugin({ + 'process.env': { + NODE_ENV: JSON.stringify(process.env.NODE_ENV) + } + }) + ]), + postcss: () => options.postcssPlugins, + resolve: { + modules: ['app', 'node_modules'], + extensions: [ + '', + '.js', + '.jsx', + '.react.js' + ], + packageMains: [ + 'jsnext:main', + 'main' + ] + }, + devtool: options.devtool, + target: 'web', // Make web variables accessible to webpack, e.g. window + stats: false, // Don't show stats in the console + progress: true +}) diff --git a/internals/webpack/webpack.dev.babel.js b/internals/webpack/webpack.dev.babel.js new file mode 100755 index 0000000..0553002 --- /dev/null +++ b/internals/webpack/webpack.dev.babel.js @@ -0,0 +1,142 @@ +/* DEVELOPMENT WEBPACK CONFIGURATION */ + +const path = require('path') +const fs = require('fs') +const webpack = require('webpack') +const HtmlWebpackPlugin = require('html-webpack-plugin') +const logger = require('../../server/logger') +const cheerio = require('cheerio') +const pkg = require(path.resolve(process.cwd(), 'package.json')) +const dllPlugin = pkg.dllPlugin + +// PostCSS plugins +const cssnext = require('postcss-cssnext') +const postcssFocus = require('postcss-focus') +const postcssReporter = require('postcss-reporter') + +const plugins = [ + new webpack.HotModuleReplacementPlugin(), // Tell webpack we want hot reloading + new webpack.NoErrorsPlugin(), + new HtmlWebpackPlugin({ + inject: true, // Inject all files that are generated by webpack, e.g. bundle.js + templateContent: templateContent() + }) +] + +module.exports = require('./webpack.base.babel')({ + // Add hot reloading in development + entry: [ + 'eventsource-polyfill', // Necessary for hot reloading with IE + 'webpack-hot-middleware/client', + path.join(process.cwd(), 'app/app.js') // Start with js/app.js + ], + + // Don't use hashes in dev mode for better performance + output: { + filename: '[name].js', + chunkFilename: '[name].chunk.js' + }, + + // Add development plugins + plugins: dependencyHandlers().concat(plugins), + + // Load the CSS in a style tag in development + cssLoaders: 'style-loader!css-loader?localIdentName=[local]__[path][name]__[hash:base64:5]&modules&importLoaders=1&sourceMap!postcss-loader', + + // Process the CSS with PostCSS + postcssPlugins: [ + postcssFocus(), // Add a :focus to every :hover + cssnext({ // Allow future CSS features to be used, also auto-prefixes the CSS... + browsers: ['last 2 versions', 'IE > 10'] // ...based on this browser list + }), + postcssReporter({ // Posts messages from plugins to the terminal + clearMessages: true + }) + ], + + // Tell babel that we want to hot-reload + babelQuery: { + presets: ['react-hmre'] + }, + + // Emit a source map for easier debugging + devtool: 'cheap-module-eval-source-map' +}) + +/** + * Select which plugins to use to optimize the bundle's handling of + * third party dependencies. + * + * If there is a dllPlugin key on the project's package.json, the + * Webpack DLL Plugin will be used. Otherwise the CommonsChunkPlugin + * will be used. + * + */ +function dependencyHandlers () { + // Don't do anything during the DLL Build step + if (process.env.BUILDING_DLL) { return [] } + + // If the package.json does not have a dllPlugin property, use the CommonsChunkPlugin + if (!dllPlugin) { + return [ + new webpack.optimize.CommonsChunkPlugin({ + name: 'vendor', + children: true, + minChunks: 2, + async: true + }) + ] + } + + const dllPath = path.resolve(process.cwd(), dllPlugin.path || 'node_modules/hyperfox-dlls') + if (!dllPlugin.dlls) { + const manifestPath = path.resolve(dllPath, 'hyperfoxLiveDeps.json') + + if (!fs.existsSync(manifestPath)) { + logger.error('The DLL manifest is missing. Please run `npm run build:dll`') + process.exit(0) + } + + return [ + new webpack.DllReferencePlugin({ + context: process.cwd(), + manifest: require(manifestPath) + }) + ] + } + + const dllManifests = Object.keys(dllPlugin.dlls).map((name) => path.join(dllPath, `/${name}.json`)) + + return dllManifests.map((manifestPath) => { + if (!fs.existsSync(path)) { + if (!fs.existsSync(manifestPath)) { + logger.error(`The following Webpack DLL manifest is missing: ${path.basename(manifestPath)}`) + logger.error(`Expected to find it in ${dllPath}`) + logger.error('Please run: npm run build:dll') + + process.exit(0) + } + } + + return new webpack.DllReferencePlugin({ + context: process.cwd(), + manifest: require(manifestPath) + }) + }) +} + +function templateContent () { + const html = fs.readFileSync( + path.resolve(process.cwd(), 'app/index.html') + ).toString() + + if (!dllPlugin) { return html } + + const doc = cheerio(html) + const body = doc.find('body') + const dllNames = !dllPlugin.dlls ? ['hyperfoxLiveDeps'] : Object.keys(dllPlugin.dlls) + + dllNames.forEach(dllName => body.append(``)) + + return doc.toString() +} diff --git a/internals/webpack/webpack.dll.babel.js b/internals/webpack/webpack.dll.babel.js new file mode 100755 index 0000000..a835685 --- /dev/null +++ b/internals/webpack/webpack.dll.babel.js @@ -0,0 +1,34 @@ +/** + * WEBPACK DLL GENERATOR + * + * This profile is used to cache webpack's module + * contexts for external library and framework type + * dependencies which will usually not change often enough + * to warrant building them from scratch every time we use + * the webpack process. + */ + +const { join } = require('path') +const defaults = require('lodash/defaultsDeep') +const webpack = require('webpack') +const pkg = require(join(process.cwd(), 'package.json')) +const dllPlugin = require('../config').dllPlugin + +if (!pkg.dllPlugin) { process.exit(0) } + +const dllConfig = defaults(pkg.dllPlugin, dllPlugin.defaults) +const outputPath = join(process.cwd(), dllConfig.path) + +module.exports = { + context: process.cwd(), + entry: dllConfig.dlls ? dllConfig.dlls : dllPlugin.entry(pkg), + devtool: 'eval', + output: { + filename: '[name].dll.js', + path: outputPath, + library: '[name]' + }, + plugins: [ + new webpack.DllPlugin({ name: '[name]', path: join(outputPath, '[name].json') }) + ] +} diff --git a/internals/webpack/webpack.prod.babel.js b/internals/webpack/webpack.prod.babel.js new file mode 100755 index 0000000..aeb45c6 --- /dev/null +++ b/internals/webpack/webpack.prod.babel.js @@ -0,0 +1,108 @@ +const path = require('path') +const webpack = require('webpack') +const HtmlWebpackPlugin = require('html-webpack-plugin') +const ExtractTextPlugin = require('extract-text-webpack-plugin') +const OfflinePlugin = require('offline-plugin') + +// PostCSS plugins +const cssnext = require('postcss-cssnext') +const postcssFocus = require('postcss-focus') +const postcssReporter = require('postcss-reporter') + +module.exports = require('./webpack.base.babel')({ + // In production, we skip all hot-reloading stuff + entry: [ + path.join(process.cwd(), 'app/app.js') + ], + + // Utilize long-term caching by adding content hashes (not compilation hashes) to compiled assets + output: { + filename: '[name].[chunkhash].js', + chunkFilename: '[name].[chunkhash].chunk.js' + }, + + // We use ExtractTextPlugin so we get a seperate CSS file instead + // of the CSS being in the JS and injected as a style tag + cssLoaders: ExtractTextPlugin.extract( + 'style-loader', + 'css-loader?modules&importLoaders=1!postcss-loader' + ), + + // In production, we minify our CSS with cssnano + postcssPlugins: [ + postcssFocus(), + cssnext({ + browsers: ['last 2 versions', 'IE > 10'] + }), + postcssReporter({ + clearMessages: true + }) + ], + plugins: [ + new webpack.optimize.CommonsChunkPlugin({ + name: 'vendor', + children: true, + minChunks: 2, + async: true + }), + + // OccurrenceOrderPlugin is needed for long-term caching to work properly. + new webpack.optimize.OccurrenceOrderPlugin(true), + + // Merge all duplicate modules + new webpack.optimize.DedupePlugin(), + + // Minify and optimize the JavaScript + new webpack.optimize.UglifyJsPlugin({ + compress: { + warnings: false // ...but do not show warnings in the console (there is a lot of them) + } + }), + + // Minify and optimize the index.html + new HtmlWebpackPlugin({ + template: 'app/index.html', + minify: { + removeComments: true, + collapseWhitespace: true, + removeRedundantAttributes: true, + useShortDoctype: true, + removeEmptyAttributes: true, + removeStyleLinkTypeAttributes: true, + keepClosingSlash: true, + minifyJS: true, + minifyCSS: true, + minifyURLs: true + }, + inject: true + }), + + // Extract the CSS into a seperate file + new ExtractTextPlugin('[name].[contenthash].css'), + + // Put it in the end to capture all the HtmlWebpackPlugin's + // assets manipulations and do leak its manipulations to HtmlWebpackPlugin + new OfflinePlugin({ + // No need to cache .htaccess. + excludes: ['.htaccess'], + + caches: { + main: [':rest:'], + + // All chunks marked as `additional`, loaded after main section + // and do not prevent SW to install. Change to `optional` if + // do not want them to be preloaded at all (cached only when first loaded) + additional: ['*.chunk.js'] + }, + + // Removes warning for about `additional` section usage + safeToUseOptionalCaches: true, + + AppCache: { + // Starting from offline-plugin:v3, AppCache by default caches only + // `main` section. This lets it use `additional` section too + caches: ['main', 'additional'] + } + }) + ] +}) diff --git a/internals/webpack/webpack.test.babel.js b/internals/webpack/webpack.test.babel.js new file mode 100755 index 0000000..3d7e31c --- /dev/null +++ b/internals/webpack/webpack.test.babel.js @@ -0,0 +1,88 @@ +/* TEST WEBPACK CONFIGURATION */ + +const path = require('path') +const webpack = require('webpack') +const modules = [ + 'app', + 'node_modules' +] + +module.exports = { + devtool: 'inline-source-map', + isparta: { + babel: { + presets: ['es2015', 'react', 'stage-0'] + } + }, + module: { + // Some libraries don't like being run through babel. + // If they gripe, put them here. + noParse: [ + /node_modules(\\|\/)sinon/, + /node_modules(\\|\/)acorn/ + ], + preLoaders: [ + { test: /\.js$/, + loader: 'isparta', + include: path.resolve('app/') + } + ], + loaders: [ + { test: /\.json$/, loader: 'json-loader' }, + { test: /\.css$/, loader: 'null-loader' }, + + // sinon.js--aliased for enzyme--expects/requires global vars. + // imports-loader allows for global vars to be injected into the module. + // See https://github.com/webpack/webpack/issues/304 + { test: /sinon(\\|\/)pkg(\\|\/)sinon\.js/, + loader: 'imports?define=>false,require=>false' + }, + { test: /\.js$/, + loader: 'babel', + exclude: [/node_modules/] + }, + { test: /\.jpe?g$|\.gif$|\.png$/i, + loader: 'null-loader' + } + ] + }, + + plugins: [ + + // Always expose NODE_ENV to webpack, in order to use `process.env.NODE_ENV` + // inside your code for any environment checks; UglifyJS will automatically + // drop any unreachable code. + new webpack.DefinePlugin({ + 'process.env': { + NODE_ENV: JSON.stringify(process.env.NODE_ENV) + } + })], + + // Some node_modules pull in Node-specific dependencies. + // Since we're running in a browser we have to stub them out. See: + // https://webpack.github.io/docs/configuration.html#node + // https://github.com/webpack/node-libs-browser/tree/master/mock + // https://github.com/webpack/jade-loader/issues/8#issuecomment-55568520 + node: { + fs: 'empty', + child_process: 'empty', + net: 'empty', + tls: 'empty' + }, + + // required for enzyme to work properly + externals: { + jsdom: 'window', + 'react/addons': true, + 'react/lib/ExecutionEnvironment': true, + 'react/lib/ReactContext': 'window' + }, + resolve: { + modulesDirectories: modules, + modules, + alias: { + // required for enzyme to work properly + sinon: 'sinon/pkg/sinon' + } + } +} From 45bdedae1e4cdb0a158a1261824df5eae81181e7 Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Sun, 12 Jun 2016 22:32:00 -0500 Subject: [PATCH 07/34] Express server --- server/index.js | 26 +++++++++ server/logger.js | 14 +++++ server/middlewares/frontendMiddleware.js | 67 ++++++++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100755 server/index.js create mode 100755 server/logger.js create mode 100755 server/middlewares/frontendMiddleware.js diff --git a/server/index.js b/server/index.js new file mode 100755 index 0000000..3392e85 --- /dev/null +++ b/server/index.js @@ -0,0 +1,26 @@ +const express = require('express') +const logger = require('./logger') + +const argv = require('minimist')(process.argv.slice(2)) +const setup = require('./middlewares/frontendMiddleware') +const resolve = require('path').resolve +const app = express() + +// app.use('/api', myApi) + +// In production we need to pass these values in instead of relying on webpack +setup(app, { + outputPath: resolve(process.cwd(), 'build'), + publicPath: '/' +}) + +// get the intended port number, use port 3000 if not provided +const port = argv.port || process.env.PORT || 3000 + +app.listen(port, (err) => { + if (err) { + return logger.error(err.message) + } + + logger.appStarted(port) +}) diff --git a/server/logger.js b/server/logger.js new file mode 100755 index 0000000..830a9c0 --- /dev/null +++ b/server/logger.js @@ -0,0 +1,14 @@ +const chalk = require('chalk') +const divider = chalk.gray('\n-----------------------------------') +const logger = { + error: err => { + console.error(chalk.red(err)) + }, + + appStarted: (port) => { + console.log(`Server started ${chalk.green('✓')}`) + console.log(`${divider}\nLocalhost: ${chalk.magenta(`http://localhost:${port}`)}${divider}`) + } +} + +module.exports = logger diff --git a/server/middlewares/frontendMiddleware.js b/server/middlewares/frontendMiddleware.js new file mode 100755 index 0000000..d9a67dc --- /dev/null +++ b/server/middlewares/frontendMiddleware.js @@ -0,0 +1,67 @@ +const express = require('express') +const path = require('path') +const compression = require('compression') +const pkg = require(path.resolve(process.cwd(), 'package.json')) + +// Dev middleware +const addDevMiddlewares = (app, webpackConfig) => { + const webpack = require('webpack') + const webpackDevMiddleware = require('webpack-dev-middleware') + const webpackHotMiddleware = require('webpack-hot-middleware') + const compiler = webpack(webpackConfig) + const middleware = webpackDevMiddleware(compiler, { + noInfo: true, + publicPath: webpackConfig.output.publicPath, + silent: true, + stats: 'errors-only' + }) + + app.use(middleware) + app.use(webpackHotMiddleware(compiler)) + + // Since webpackDevMiddleware uses memory-fs internally to store build artifacts, we use it instead + const fs = middleware.fileSystem + + if (pkg.dllPlugin) { + app.get(/\.dll\.js$/, (req, res) => { + const filename = req.path.replace(/^\//, '') + res.sendFile(path.join(process.cwd(), pkg.dllPlugin.path, filename)) + }) + } + + app.get('*', (req, res) => { + fs.readFile(path.join(compiler.outputPath, 'index.html'), (err, file) => { + if (err) { + res.sendStatus(404) + } else { + res.send(file.toString()) + } + }) + }) +} + +// Production middlewares +const addProdMiddlewares = (app, options) => { + const publicPath = options.publicPath || '/' + const outputPath = options.outputPath || path.resolve(process.cwd(), 'build') + + // compression middleware compresses server responses + app.use(compression()) + app.use(publicPath, express.static(outputPath)) + + app.get('*', (req, res) => res.sendFile(path.resolve(outputPath, 'index.html'))) +} + +// Front-end middleware +module.exports = (app, options) => { + const isProd = process.env.NODE_ENV === 'production' + + if (isProd) { + addProdMiddlewares(app, options) + } else { + const webpackConfig = require('../../internals/webpack/webpack.dev.babel') + addDevMiddlewares(app, webpackConfig) + } + + return app +} From 309d134aa9a6bd631e07415b2ceeb173d44e70c2 Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Sun, 12 Jun 2016 22:32:00 -0500 Subject: [PATCH 08/34] manifest.json --- app/manifest.json | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100755 app/manifest.json diff --git a/app/manifest.json b/app/manifest.json new file mode 100755 index 0000000..a2ad609 --- /dev/null +++ b/app/manifest.json @@ -0,0 +1,33 @@ +{ + "name": "Hyperfox", + "icons": [ + { + "src": "favicon.png", + "sizes": "48x48", + "type": "image/png", + "density": 1.0 + }, + { + "src": "favicon.png", + "sizes": "96x96", + "type": "image/png", + "density": 2.0 + }, + { + "src": "favicon.png", + "sizes": "144x144", + "type": "image/png", + "density": 3.0 + }, + { + "src": "favicon.png", + "sizes": "192x192", + "type": "image/png", + "density": 4.0 + } + ], + "start_url": "index.html", + "display": "standalone", + "orientation": "portrait", + "background_color": "#FFFFFF" +} From a56b03ebdc2c425d55ca79fea23cb2e7ba81f18b Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Mon, 13 Jun 2016 22:32:00 -0500 Subject: [PATCH 09/34] Add NavigationBar component and Logo --- app/app.js | 4 +-- app/components/Icons/Logo.js | 22 ++++++++++++ app/components/NavigationBar/index.js | 23 ++++++++++++ app/components/NavigationBar/styles.css | 5 +++ .../NavigationBar/tests/index.test.js | 35 +++++++++++++++++++ app/containers/App/index.js | 6 ++-- app/containers/{HomePage => Logger}/index.js | 0 app/routes.js | 2 +- internals/webpack/webpack.dev.babel.js | 1 + internals/webpack/webpack.prod.babel.js | 1 + package.json | 1 + 11 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 app/components/Icons/Logo.js create mode 100755 app/components/NavigationBar/index.js create mode 100755 app/components/NavigationBar/styles.css create mode 100755 app/components/NavigationBar/tests/index.test.js rename app/containers/{HomePage => Logger}/index.js (100%) diff --git a/app/app.js b/app/app.js index e1573ab..6dcd2ed 100755 --- a/app/app.js +++ b/app/app.js @@ -55,5 +55,5 @@ ReactDOM.render( // Install ServiceWorker and AppCache in the end since // it's not most important operation and if main code fails, // we do not want it installed -import { install } from 'offline-plugin/runtime' -install() +// import { install } from 'offline-plugin/runtime' +// install() diff --git a/app/components/Icons/Logo.js b/app/components/Icons/Logo.js new file mode 100644 index 0000000..92dcf1f --- /dev/null +++ b/app/components/Icons/Logo.js @@ -0,0 +1,22 @@ +import React, {PropTypes} from 'react' + +export default function Logo (props) { + return ( +
+ + + +
+ ) +} + +Logo.propTypes = { + className: PropTypes.string, + width: PropTypes.string, + height: PropTypes.string +} diff --git a/app/components/NavigationBar/index.js b/app/components/NavigationBar/index.js new file mode 100755 index 0000000..2adf6f4 --- /dev/null +++ b/app/components/NavigationBar/index.js @@ -0,0 +1,23 @@ +import React, { PropTypes } from 'react' + +import Logo from 'components/Icons/Logo' + +import styles from './styles.css' + +export default class NavigationBar extends React.Component { + static propTypes = { + className: PropTypes.string + } + + constructor (props) { + super(props) + } + + render () { + return ( +
+ +
+ ) + } +} diff --git a/app/components/NavigationBar/styles.css b/app/components/NavigationBar/styles.css new file mode 100755 index 0000000..99454a2 --- /dev/null +++ b/app/components/NavigationBar/styles.css @@ -0,0 +1,5 @@ +.Logo{ + path{ + fill: #11f; + } +} diff --git a/app/components/NavigationBar/tests/index.test.js b/app/components/NavigationBar/tests/index.test.js new file mode 100755 index 0000000..a84648b --- /dev/null +++ b/app/components/NavigationBar/tests/index.test.js @@ -0,0 +1,35 @@ +/* Testing our NavigationBar component */ + +import NavigationBar from '../index' + +import Logo from 'components/Icons/Logo' +import styles from '../styles.css' + +import expect from 'expect' +import { shallow } from 'enzyme' +import React from 'react' + +describe('', () => { + it('should render the Logo', () => { + const navLogo = () + const renderedComponent = shallow( + + ) + expect(renderedComponent.contains(navLogo)).toEqual(true) + }) + + /* it('should adopt the className', () => { + const renderedComponent = shallow() + expect(renderedComponent.find('a').hasClass('test')).toEqual(true) + }) + + it('should adopt the href', () => { + const renderedComponent = shallow() + expect(renderedComponent.prop('href')).toEqual('mxstbr.com') + }) + + it('should adopt the target', () => { + const renderedComponent = shallow() + expect(renderedComponent.prop('target')).toEqual('_blank') + }) */ +}) diff --git a/app/containers/App/index.js b/app/containers/App/index.js index e578c4f..e618e3b 100755 --- a/app/containers/App/index.js +++ b/app/containers/App/index.js @@ -3,16 +3,18 @@ * contain code that should be seen on all pages. (e.g. navigation bar) */ -import React from 'react' +import React, {PropTypes} from 'react' +import NavigationBar from 'components/NavigationBar' export default class App extends React.Component { static propTypes = { - children: React.PropTypes.node + children: PropTypes.node } render () { return (
+ {this.props.children}
) diff --git a/app/containers/HomePage/index.js b/app/containers/Logger/index.js similarity index 100% rename from app/containers/HomePage/index.js rename to app/containers/Logger/index.js diff --git a/app/routes.js b/app/routes.js index b9e9c48..8ed3e7a 100755 --- a/app/routes.js +++ b/app/routes.js @@ -17,7 +17,7 @@ export default function createRoutes () { name: 'home', getComponent (nextState, cb) { const importModules = Promise.all([ - System.import('containers/HomePage') + System.import('containers/Logger') ]) const renderRoute = loadModule(cb) diff --git a/internals/webpack/webpack.dev.babel.js b/internals/webpack/webpack.dev.babel.js index 0553002..19641d6 100755 --- a/internals/webpack/webpack.dev.babel.js +++ b/internals/webpack/webpack.dev.babel.js @@ -45,6 +45,7 @@ module.exports = require('./webpack.base.babel')({ // Process the CSS with PostCSS postcssPlugins: [ + require('precss')(), postcssFocus(), // Add a :focus to every :hover cssnext({ // Allow future CSS features to be used, also auto-prefixes the CSS... browsers: ['last 2 versions', 'IE > 10'] // ...based on this browser list diff --git a/internals/webpack/webpack.prod.babel.js b/internals/webpack/webpack.prod.babel.js index aeb45c6..11c4ecc 100755 --- a/internals/webpack/webpack.prod.babel.js +++ b/internals/webpack/webpack.prod.babel.js @@ -30,6 +30,7 @@ module.exports = require('./webpack.base.babel')({ // In production, we minify our CSS with cssnano postcssPlugins: [ + require('precss')(), postcssFocus(), cssnext({ browsers: ['last 2 versions', 'IE > 10'] diff --git a/package.json b/package.json index 3b96dde..c046070 100644 --- a/package.json +++ b/package.json @@ -134,6 +134,7 @@ "postcss-focus": "^1.0.0", "postcss-loader": "^0.9.1", "postcss-reporter": "^1.3.3", + "precss": "^1.4.0", "rimraf": "^2.5.2", "shelljs": "^0.7.0", "sinon": "^2.0.0-pre", From 7f53d283ad4d946b285af155e461776bbf19a554 Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Tue, 14 Jun 2016 22:32:00 -0500 Subject: [PATCH 10/34] Implement i18n and Bulma Framework --- app/app.js | 35 +++++++++++----- app/components/NavigationBar/index.js | 26 ++++++++---- app/components/NavigationBar/messages.js | 8 ++++ app/components/NavigationBar/styles.css | 31 +++++++++++++- app/containers/App/index.js | 2 +- app/containers/LanguageProvider/actions.js | 14 +++++++ app/containers/LanguageProvider/constants.js | 7 ++++ app/containers/LanguageProvider/index.js | 40 +++++++++++++++++++ app/containers/LanguageProvider/reducer.js | 23 +++++++++++ app/containers/LanguageProvider/selectors.js | 12 ++++++ .../LanguageProvider/tests/actions.test.js | 15 +++++++ .../LanguageProvider/tests/index.test.js | 35 ++++++++++++++++ .../LanguageProvider/tests/reducer.test.js | 11 +++++ .../LanguageProvider/tests/selectors.test.js | 14 +++++++ app/i18n.js | 30 ++++++++++++++ app/index.html | 2 + app/translations/en.json | 7 ++++ app/translations/es.json | 7 ++++ package.json | 4 ++ 19 files changed, 303 insertions(+), 20 deletions(-) create mode 100644 app/components/NavigationBar/messages.js create mode 100755 app/containers/LanguageProvider/actions.js create mode 100755 app/containers/LanguageProvider/constants.js create mode 100755 app/containers/LanguageProvider/index.js create mode 100755 app/containers/LanguageProvider/reducer.js create mode 100755 app/containers/LanguageProvider/selectors.js create mode 100755 app/containers/LanguageProvider/tests/actions.test.js create mode 100755 app/containers/LanguageProvider/tests/index.test.js create mode 100755 app/containers/LanguageProvider/tests/reducer.test.js create mode 100755 app/containers/LanguageProvider/tests/selectors.test.js create mode 100644 app/i18n.js create mode 100755 app/translations/en.json create mode 100755 app/translations/es.json diff --git a/app/app.js b/app/app.js index 6dcd2ed..ad157ff 100755 --- a/app/app.js +++ b/app/app.js @@ -17,8 +17,14 @@ import { syncHistoryWithStore } from 'react-router-redux' import useScroll from 'react-router-scroll' import configureStore from './store' +// Import Language Provider +import LanguageProvider from 'containers/LanguageProvider' +// Import i18n messages +import { translationMessages } from './i18n' + // Import the CSS reset, which HtmlWebpackPlugin transfers to the build folder -import 'sanitize.css/lib/sanitize.css' +// import 'sanitize.css/lib/sanitize.css' +import 'bulma/css/bulma.css' // Create redux store with history // this uses the singleton browserHistory provided by react-router @@ -42,16 +48,25 @@ const rootRoute = { component: App, childRoutes: createRoutes(store) } +const render = () => { + ReactDOM.render( + + + + + , + document.getElementById('app') + ) +} -ReactDOM.render( - - - , - document.getElementById('app') -) - +// Chunked polyfill for browsers without Intl support +if (!window.Intl) { + System.import('intl').then(render) +} else { + render() +} // Install ServiceWorker and AppCache in the end since // it's not most important operation and if main code fails, // we do not want it installed diff --git a/app/components/NavigationBar/index.js b/app/components/NavigationBar/index.js index 2adf6f4..73fcc38 100755 --- a/app/components/NavigationBar/index.js +++ b/app/components/NavigationBar/index.js @@ -1,22 +1,32 @@ -import React, { PropTypes } from 'react' +import React from 'react' +import {FormattedMessage} from 'react-intl' +import classNames from 'classnames' import Logo from 'components/Icons/Logo' - +import messages from './messages' import styles from './styles.css' export default class NavigationBar extends React.Component { - static propTypes = { - className: PropTypes.string - } - constructor (props) { super(props) } render () { return ( -
- +
+
+ + / Live +
+
+

+ + + + + +

+
) } diff --git a/app/components/NavigationBar/messages.js b/app/components/NavigationBar/messages.js new file mode 100644 index 0000000..7833668 --- /dev/null +++ b/app/components/NavigationBar/messages.js @@ -0,0 +1,8 @@ +import { defineMessages } from 'react-intl' + +export default defineMessages({ + searchMessage: { + id: 'hyperfox.components.NavigationBar.search.message', + defaultMessage: 'Search.' + } +}) diff --git a/app/components/NavigationBar/styles.css b/app/components/NavigationBar/styles.css index 99454a2..c845466 100755 --- a/app/components/NavigationBar/styles.css +++ b/app/components/NavigationBar/styles.css @@ -1,5 +1,34 @@ +.NavigationBar{ + &__Logo{ + span{ + float: left; + } + &__Live{ + font-size: 25px; + position: relative; + top: 15px; + left: 3px; + } + } + &__Search{ + &__Input{ + float: right; + top: 15px; + .fa{ + font-size: 15px !important; + } + } + } +} + .Logo{ path{ - fill: #11f; + fill: #ed6c63; + transition: fill .4s linear; + } + &:hover{ + path{ + fill: #DB0F2E; + } } } diff --git a/app/containers/App/index.js b/app/containers/App/index.js index e618e3b..4d1d8c3 100755 --- a/app/containers/App/index.js +++ b/app/containers/App/index.js @@ -13,7 +13,7 @@ export default class App extends React.Component { render () { return ( -
+
{this.props.children}
diff --git a/app/containers/LanguageProvider/actions.js b/app/containers/LanguageProvider/actions.js new file mode 100755 index 0000000..e5a40f4 --- /dev/null +++ b/app/containers/LanguageProvider/actions.js @@ -0,0 +1,14 @@ +/* + * + * LanguageProvider actions + * + */ + +import {CHANGE_LOCALE} from './constants' + +export function changeLocale (languageLocale) { + return { + type: CHANGE_LOCALE, + locale: languageLocale + } +} diff --git a/app/containers/LanguageProvider/constants.js b/app/containers/LanguageProvider/constants.js new file mode 100755 index 0000000..e700abc --- /dev/null +++ b/app/containers/LanguageProvider/constants.js @@ -0,0 +1,7 @@ +/* + * + * LanguageProvider constants + * + */ + +export const CHANGE_LOCALE = 'app/LanguageToggle/CHANGE_LOCALE' diff --git a/app/containers/LanguageProvider/index.js b/app/containers/LanguageProvider/index.js new file mode 100755 index 0000000..144f444 --- /dev/null +++ b/app/containers/LanguageProvider/index.js @@ -0,0 +1,40 @@ +/* + * + * LanguageProvider + * + * this component connects the redux state language locale to the + * IntlProvider component and i18n messages (loaded from `app/translations`) + */ + +import React from 'react' +import { connect } from 'react-redux' +import { createSelector } from 'reselect' +import { IntlProvider } from 'react-intl' +import { selectLocale } from './selectors' + +export class LanguageProvider extends React.Component { + render () { + return ( + + {this.props.children} + + ) + } +} + +LanguageProvider.propTypes = { + locale: React.PropTypes.string, + messages: React.PropTypes.object, + children: React.PropTypes.element.isRequired +} + +const mapStateToProps = createSelector( + selectLocale(), + (locale) => ({locale}) +) + +function mapDispatchToProps (dispatch) { + return {dispatch} +} + +export default connect(mapStateToProps, mapDispatchToProps)(LanguageProvider) diff --git a/app/containers/LanguageProvider/reducer.js b/app/containers/LanguageProvider/reducer.js new file mode 100755 index 0000000..f370dd7 --- /dev/null +++ b/app/containers/LanguageProvider/reducer.js @@ -0,0 +1,23 @@ +/* + * + * LanguageProvider reducer + * + */ + +import { fromJS } from 'immutable' +import {CHANGE_LOCALE} from './constants' + +const initialState = fromJS({ + locale: 'en' +}) + +function languageProviderReducer (state = initialState, action) { + switch (action.type) { + case CHANGE_LOCALE: + return state.set('locale', action.locale) + default: + return state + } +} + +export default languageProviderReducer diff --git a/app/containers/LanguageProvider/selectors.js b/app/containers/LanguageProvider/selectors.js new file mode 100755 index 0000000..cf69135 --- /dev/null +++ b/app/containers/LanguageProvider/selectors.js @@ -0,0 +1,12 @@ +import { createSelector } from 'reselect' + +/* Direct selector to the languageToggle state domain */ +const selectLanguage = () => state => state.get('language') + +/* Select the language locale */ +const selectLocale = () => createSelector( + selectLanguage(), + (languageState) => languageState.get('locale') +) + +export {selectLanguage, selectLocale} diff --git a/app/containers/LanguageProvider/tests/actions.test.js b/app/containers/LanguageProvider/tests/actions.test.js new file mode 100755 index 0000000..72f872e --- /dev/null +++ b/app/containers/LanguageProvider/tests/actions.test.js @@ -0,0 +1,15 @@ +import expect from 'expect' +import {changeLocale} from '../actions' +import {CHANGE_LOCALE} from '../constants' + +describe('LanguageProvider actions', () => { + describe('Change Local Action', () => { + it('has a type of CHANGE_LOCALE', () => { + const expected = { + type: CHANGE_LOCALE, + locale: 'de' + } + expect(changeLocale('de')).toEqual(expected) + }) + }) +}) diff --git a/app/containers/LanguageProvider/tests/index.test.js b/app/containers/LanguageProvider/tests/index.test.js new file mode 100755 index 0000000..60191f3 --- /dev/null +++ b/app/containers/LanguageProvider/tests/index.test.js @@ -0,0 +1,35 @@ +import LanguageProvider from '../index' + +import expect from 'expect' +import { shallow } from 'enzyme' +import { FormattedMessage, defineMessages } from 'react-intl' +import configureStore from '../../../store' +import React from 'react' +import { Provider } from 'react-redux' +import { browserHistory } from 'react-router' +import { translatedMessages } from '../../../i18n' + +describe('', () => { + let store + + before(() => { + store = configureStore({}, browserHistory) + }) + + it('should render the default language messages', () => { + const messages = defineMessages({ + someMessage: { + id: 'some.id', + defaultMessage: 'This is some default message' + } + }) + const renderedComponent = shallow( + + + + + + ) + expect(renderedComponent.contains()).toEqual(true) + }) +}) diff --git a/app/containers/LanguageProvider/tests/reducer.test.js b/app/containers/LanguageProvider/tests/reducer.test.js new file mode 100755 index 0000000..f6e37a2 --- /dev/null +++ b/app/containers/LanguageProvider/tests/reducer.test.js @@ -0,0 +1,11 @@ +import expect from 'expect' +import languageProviderReducer from '../reducer' +import { fromJS } from 'immutable' + +describe('languageProviderReducer', () => { + it('returns the initial state', () => { + expect(languageProviderReducer(undefined, {})).toEqual(fromJS({ + locale: 'en' + })) + }) +}) diff --git a/app/containers/LanguageProvider/tests/selectors.test.js b/app/containers/LanguageProvider/tests/selectors.test.js new file mode 100755 index 0000000..ddae78a --- /dev/null +++ b/app/containers/LanguageProvider/tests/selectors.test.js @@ -0,0 +1,14 @@ +import {selectLanguage} from '../selectors' +import {fromJS} from 'immutable' +import expect from 'expect' + +describe('selectLanguage', () => { + const globalSelector = selectLanguage() + it('should select the global state', () => { + const globalState = fromJS({}) + const mockedState = fromJS({ + language: globalState + }) + expect(globalSelector(mockedState)).toEqual(globalState) + }) +}) diff --git a/app/i18n.js b/app/i18n.js new file mode 100644 index 0000000..c848bac --- /dev/null +++ b/app/i18n.js @@ -0,0 +1,30 @@ +/* This will setup the i18n language files and locale data for hiperfox */ +import { addLocaleData } from 'react-intl' + +import enLocaleData from 'react-intl/locale-data/en' +import esLocaleData from 'react-intl/locale-data/es' + +export const appLocales = [ + 'en', + 'es' +] + +import enTranslationMessages from './translations/en.json' +import esTranslationMessages from './translations/es.json' + +addLocaleData(enLocaleData) +addLocaleData(esLocaleData) + +const formatTranslationMessages = (messages) => { + const formattedMessages = {} + for (const message of messages) { + formattedMessages[message.id] = message.message || message.defaultMessage + } + + return formattedMessages +} + +export const translationMessages = { + en: formatTranslationMessages(enTranslationMessages), + es: formatTranslationMessages(esTranslationMessages) +} diff --git a/app/index.html b/app/index.html index a50e1ec..7e4192e 100755 --- a/app/index.html +++ b/app/index.html @@ -4,6 +4,8 @@ + + Hyperfox diff --git a/app/translations/en.json b/app/translations/en.json new file mode 100755 index 0000000..5a13b6b --- /dev/null +++ b/app/translations/en.json @@ -0,0 +1,7 @@ +[ + { + "id": "hyperfox.components.NavigationBar.search.message", + "defaultMessage": "Search.", + "message": "Search." + } +] diff --git a/app/translations/es.json b/app/translations/es.json new file mode 100755 index 0000000..40ac307 --- /dev/null +++ b/app/translations/es.json @@ -0,0 +1,7 @@ +[ + { + "id": "hyperfox.components.NavigationBar.search.message", + "defaultMessage": "Buscar.", + "message": "Buscar." + } +] diff --git a/package.json b/package.json index c046070..ee362ea 100644 --- a/package.json +++ b/package.json @@ -62,15 +62,18 @@ }, "dependencies": { "babel-polyfill": "^6.7.4", + "bulma": "0.0.28", "chalk": "^1.1.3", "compression": "^1.6.1", "express": "^4.13.4", "fontfaceobserver": "^1.7.1", "history": "^2.1.0", "immutable": "^3.8.1", + "intl": "^1.2.4", "minimist": "^1.2.0", "react": "^15.0.1", "react-dom": "^15.0.1", + "react-intl": "^2.1.3", "react-redux": "^4.4.5", "react-router": "^2.3.0", "react-router-redux": "^4.0.4", @@ -86,6 +89,7 @@ "babel-core": "^6.7.7", "babel-eslint": "^6.0.5", "babel-loader": "^6.2.4", + "babel-plugin-react-intl": "^2.1.3", "babel-plugin-react-transform": "^2.0.2", "babel-plugin-transform-react-constant-elements": "^6.8.0", "babel-plugin-transform-react-inline-elements": "^6.8.0", From 78e3c63f727630e857f0cef4e51cc6c7a2f3d085 Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Wed, 15 Jun 2016 22:32:00 -0500 Subject: [PATCH 11/34] Fix i18n --- app/app.js | 2 +- app/reducers.js | 2 ++ app/translations/en.json | 4 ++-- app/translations/es.json | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/app.js b/app/app.js index ad157ff..ab751b3 100755 --- a/app/app.js +++ b/app/app.js @@ -51,7 +51,7 @@ const rootRoute = { const render = () => { ReactDOM.render( - + diff --git a/app/reducers.js b/app/reducers.js index 727a7b5..5e289c7 100755 --- a/app/reducers.js +++ b/app/reducers.js @@ -5,6 +5,7 @@ import { combineReducers } from 'redux-immutable' import { fromJS } from 'immutable' import { LOCATION_CHANGE } from 'react-router-redux' +import languageProviderReducer from 'containers/LanguageProvider/reducer' /* * routeReducer @@ -40,6 +41,7 @@ function routeReducer (state = routeInitialState, action) { export default function createReducer (asyncReducers) { return combineReducers({ route: routeReducer, + language: languageProviderReducer, ...asyncReducers }) } diff --git a/app/translations/en.json b/app/translations/en.json index 5a13b6b..5719311 100755 --- a/app/translations/en.json +++ b/app/translations/en.json @@ -1,7 +1,7 @@ [ { "id": "hyperfox.components.NavigationBar.search.message", - "defaultMessage": "Search.", - "message": "Search." + "defaultMessage": "Search", + "message": "Search" } ] diff --git a/app/translations/es.json b/app/translations/es.json index 40ac307..660cf50 100755 --- a/app/translations/es.json +++ b/app/translations/es.json @@ -1,7 +1,7 @@ [ { "id": "hyperfox.components.NavigationBar.search.message", - "defaultMessage": "Buscar.", - "message": "Buscar." + "defaultMessage": "Buscar", + "message": "Buscar" } ] From 4012ba9e815a4ed62de8e4d42ccbea07c788bc4e Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Wed, 15 Jun 2016 22:32:00 -0500 Subject: [PATCH 12/34] Fix i18n Test --- app/containers/LanguageProvider/actions.js | 6 +----- app/containers/LanguageProvider/constants.js | 6 +----- app/containers/LanguageProvider/index.js | 5 +---- app/containers/LanguageProvider/reducer.js | 6 +----- app/containers/LanguageProvider/tests/actions.test.js | 4 ++-- 5 files changed, 6 insertions(+), 21 deletions(-) diff --git a/app/containers/LanguageProvider/actions.js b/app/containers/LanguageProvider/actions.js index e5a40f4..5030d68 100755 --- a/app/containers/LanguageProvider/actions.js +++ b/app/containers/LanguageProvider/actions.js @@ -1,8 +1,4 @@ -/* - * - * LanguageProvider actions - * - */ +/* LanguageProvider actions */ import {CHANGE_LOCALE} from './constants' diff --git a/app/containers/LanguageProvider/constants.js b/app/containers/LanguageProvider/constants.js index e700abc..730444c 100755 --- a/app/containers/LanguageProvider/constants.js +++ b/app/containers/LanguageProvider/constants.js @@ -1,7 +1,3 @@ -/* - * - * LanguageProvider constants - * - */ +/* LanguageProvider constants */ export const CHANGE_LOCALE = 'app/LanguageToggle/CHANGE_LOCALE' diff --git a/app/containers/LanguageProvider/index.js b/app/containers/LanguageProvider/index.js index 144f444..ca17662 100755 --- a/app/containers/LanguageProvider/index.js +++ b/app/containers/LanguageProvider/index.js @@ -1,7 +1,4 @@ -/* - * - * LanguageProvider - * +/* LanguageProvider * this component connects the redux state language locale to the * IntlProvider component and i18n messages (loaded from `app/translations`) */ diff --git a/app/containers/LanguageProvider/reducer.js b/app/containers/LanguageProvider/reducer.js index f370dd7..d752735 100755 --- a/app/containers/LanguageProvider/reducer.js +++ b/app/containers/LanguageProvider/reducer.js @@ -1,8 +1,4 @@ -/* - * - * LanguageProvider reducer - * - */ +/* LanguageProvider reducer */ import { fromJS } from 'immutable' import {CHANGE_LOCALE} from './constants' diff --git a/app/containers/LanguageProvider/tests/actions.test.js b/app/containers/LanguageProvider/tests/actions.test.js index 72f872e..86647e6 100755 --- a/app/containers/LanguageProvider/tests/actions.test.js +++ b/app/containers/LanguageProvider/tests/actions.test.js @@ -7,9 +7,9 @@ describe('LanguageProvider actions', () => { it('has a type of CHANGE_LOCALE', () => { const expected = { type: CHANGE_LOCALE, - locale: 'de' + locale: 'es' } - expect(changeLocale('de')).toEqual(expected) + expect(changeLocale('es')).toEqual(expected) }) }) }) From 5b40f7f64b1008300165546e38ddacc8bb299b59 Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Thu, 16 Jun 2016 22:32:00 -0500 Subject: [PATCH 13/34] Create Notification component --- app/components/Notification/index.js | 31 ++++++++++++++++ .../Notification/tests/index.test.js | 35 +++++++++++++++++++ app/containers/Logger/index.js | 18 +++++++--- app/containers/Logger/messages.js | 12 +++++++ app/translations/en.json | 10 ++++++ 5 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 app/components/Notification/index.js create mode 100644 app/components/Notification/tests/index.test.js create mode 100644 app/containers/Logger/messages.js diff --git a/app/components/Notification/index.js b/app/components/Notification/index.js new file mode 100644 index 0000000..6313b36 --- /dev/null +++ b/app/components/Notification/index.js @@ -0,0 +1,31 @@ +import React, {PropTypes} from 'react' +import {FormattedMessage} from 'react-intl' +import classNames from 'classnames' + +export default class Notification extends React.Component { + static propTypes = { + alertStyle: PropTypes.string, + message: PropTypes.string + } + + constructor (props) { + super(props) + } + + render () { + const alertStyles = { + normal: '', + info: 'is-info', + success: 'is-success', + warning: 'is-warning', + danger: 'is-danger' + } + + return ( +
+ + +
+ ) + } +} diff --git a/app/components/Notification/tests/index.test.js b/app/components/Notification/tests/index.test.js new file mode 100644 index 0000000..a84648b --- /dev/null +++ b/app/components/Notification/tests/index.test.js @@ -0,0 +1,35 @@ +/* Testing our NavigationBar component */ + +import NavigationBar from '../index' + +import Logo from 'components/Icons/Logo' +import styles from '../styles.css' + +import expect from 'expect' +import { shallow } from 'enzyme' +import React from 'react' + +describe('', () => { + it('should render the Logo', () => { + const navLogo = () + const renderedComponent = shallow( + + ) + expect(renderedComponent.contains(navLogo)).toEqual(true) + }) + + /* it('should adopt the className', () => { + const renderedComponent = shallow() + expect(renderedComponent.find('a').hasClass('test')).toEqual(true) + }) + + it('should adopt the href', () => { + const renderedComponent = shallow() + expect(renderedComponent.prop('href')).toEqual('mxstbr.com') + }) + + it('should adopt the target', () => { + const renderedComponent = shallow() + expect(renderedComponent.prop('target')).toEqual('_blank') + }) */ +}) diff --git a/app/containers/Logger/index.js b/app/containers/Logger/index.js index ca2acf1..6d2d50e 100755 --- a/app/containers/Logger/index.js +++ b/app/containers/Logger/index.js @@ -1,14 +1,24 @@ -/* HomePage - * This is the first thing users see of our App, at the '/' route - */ +/* Logger */ import React from 'react' +import Notification from 'components/Notification' + +import messages from './messages' export default class HomePage extends React.Component { render () { return ( -

Hyperfox!

+
+ + +
) } } diff --git a/app/containers/Logger/messages.js b/app/containers/Logger/messages.js new file mode 100644 index 0000000..5b1aa49 --- /dev/null +++ b/app/containers/Logger/messages.js @@ -0,0 +1,12 @@ +import { defineMessages } from 'react-intl' + +export default defineMessages({ + noConnected: { + id: 'hyperfox.containers.Logger.Notification.noconnected.message', + defaultMessage: 'Could not connect to the Hyperfox API. Seems like hyperfox is not running on your local box.' + }, + noData: { + id: 'hyperfox.containers.Logger.Notification.nodata.message', + defaultMessage: 'No data to show yet.' + } +}) diff --git a/app/translations/en.json b/app/translations/en.json index 5719311..18df2ae 100755 --- a/app/translations/en.json +++ b/app/translations/en.json @@ -3,5 +3,15 @@ "id": "hyperfox.components.NavigationBar.search.message", "defaultMessage": "Search", "message": "Search" + }, + { + "id": "hyperfox.containers.Logger.Notification.noconnected.message", + "defaultMessage": "Could not connect to the Hyperfox API. Seems like hyperfox is not running on your local box.", + "message": "Could not connect to the Hyperfox API. Seems like hyperfox is not running on your local box." + }, + { + "id": "hyperfox.containers.Logger.Notification.nodata.message", + "defaultMessage": "No data to show yet.", + "message": "No data to show yet." } ] From 9b96ed677418a15a80ce6426c3cb1a613a05d7c8 Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Fri, 17 Jun 2016 22:32:00 -0500 Subject: [PATCH 14/34] Create test for Notification component --- .../NavigationBar/tests/index.test.js | 15 ------- app/components/Notification/index.js | 3 +- .../Notification/tests/index.test.js | 42 +++++++++---------- 3 files changed, 20 insertions(+), 40 deletions(-) diff --git a/app/components/NavigationBar/tests/index.test.js b/app/components/NavigationBar/tests/index.test.js index a84648b..8c20525 100755 --- a/app/components/NavigationBar/tests/index.test.js +++ b/app/components/NavigationBar/tests/index.test.js @@ -17,19 +17,4 @@ describe('', () => { ) expect(renderedComponent.contains(navLogo)).toEqual(true) }) - - /* it('should adopt the className', () => { - const renderedComponent = shallow() - expect(renderedComponent.find('a').hasClass('test')).toEqual(true) - }) - - it('should adopt the href', () => { - const renderedComponent = shallow() - expect(renderedComponent.prop('href')).toEqual('mxstbr.com') - }) - - it('should adopt the target', () => { - const renderedComponent = shallow() - expect(renderedComponent.prop('target')).toEqual('_blank') - }) */ }) diff --git a/app/components/Notification/index.js b/app/components/Notification/index.js index 6313b36..426ab9f 100644 --- a/app/components/Notification/index.js +++ b/app/components/Notification/index.js @@ -5,7 +5,7 @@ import classNames from 'classnames' export default class Notification extends React.Component { static propTypes = { alertStyle: PropTypes.string, - message: PropTypes.string + message: PropTypes.object } constructor (props) { @@ -20,7 +20,6 @@ export default class Notification extends React.Component { warning: 'is-warning', danger: 'is-danger' } - return (
diff --git a/app/components/Notification/tests/index.test.js b/app/components/Notification/tests/index.test.js index a84648b..ea3e487 100644 --- a/app/components/Notification/tests/index.test.js +++ b/app/components/Notification/tests/index.test.js @@ -1,35 +1,31 @@ /* Testing our NavigationBar component */ -import NavigationBar from '../index' - -import Logo from 'components/Icons/Logo' -import styles from '../styles.css' +import Notification from '../index' import expect from 'expect' import { shallow } from 'enzyme' import React from 'react' -describe('', () => { - it('should render the Logo', () => { - const navLogo = () +const message = { + id: 'hyperfox.test', + description: 'Major Tom', + defaultMessage: 'Ground Control To Major Tom' +} + +describe('', () => { + it('should render the Notification with is-danger class', () => { const renderedComponent = shallow( - + ) - expect(renderedComponent.contains(navLogo)).toEqual(true) - }) - - /* it('should adopt the className', () => { - const renderedComponent = shallow() - expect(renderedComponent.find('a').hasClass('test')).toEqual(true) + expect(renderedComponent.hasClass('is-danger')).toEqual(true) }) - - it('should adopt the href', () => { - const renderedComponent = shallow() - expect(renderedComponent.prop('href')).toEqual('mxstbr.com') + it('should render the Notification with is-success class', () => { + const renderedComponent = shallow( + + ) + expect(renderedComponent.hasClass('is-success')).toEqual(true) }) - - it('should adopt the target', () => { - const renderedComponent = shallow() - expect(renderedComponent.prop('target')).toEqual('_blank') - }) */ }) From 3ba56a3aada13803ee9de8241b17f405c2656f1d Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Sat, 18 Jun 2016 22:32:00 -0500 Subject: [PATCH 15/34] Responsive navbar --- app/components/NavigationBar/index.js | 38 ++++++++++++------------- app/components/NavigationBar/styles.css | 14 ++++----- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/app/components/NavigationBar/index.js b/app/components/NavigationBar/index.js index 73fcc38..41bcf15 100755 --- a/app/components/NavigationBar/index.js +++ b/app/components/NavigationBar/index.js @@ -1,33 +1,33 @@ import React from 'react' -import {FormattedMessage} from 'react-intl' + import classNames from 'classnames' +import styles from './styles.css' -import Logo from 'components/Icons/Logo' +import {FormattedMessage} from 'react-intl' import messages from './messages' -import styles from './styles.css' -export default class NavigationBar extends React.Component { - constructor (props) { - super(props) - } +import Logo from 'components/Icons/Logo' - render () { - return ( -
-
- - / Live -
-
+export default function NavigationBar () { + return ( + + ) } diff --git a/app/components/NavigationBar/styles.css b/app/components/NavigationBar/styles.css index c845466..df2b842 100755 --- a/app/components/NavigationBar/styles.css +++ b/app/components/NavigationBar/styles.css @@ -1,19 +1,15 @@ .NavigationBar{ + background-color: #455a64; + padding: 0 10px; &__Logo{ - span{ - float: left; - } &__Live{ - font-size: 25px; - position: relative; - top: 15px; - left: 3px; + font-size: 20px; + color: #fff; + padding: 0; } } &__Search{ &__Input{ - float: right; - top: 15px; .fa{ font-size: 15px !important; } From 4e659a335a9d27010eb9f13613d0fa0a25b45713 Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Sun, 19 Jun 2016 22:32:00 -0500 Subject: [PATCH 16/34] Add Logs placeholders --- app/containers/Logger/index.js | 62 ++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/app/containers/Logger/index.js b/app/containers/Logger/index.js index 6d2d50e..e552b11 100755 --- a/app/containers/Logger/index.js +++ b/app/containers/Logger/index.js @@ -5,11 +5,50 @@ import Notification from 'components/Notification' import messages from './messages' -export default class HomePage extends React.Component { +const logs = { + date: '12:51:12', + method: 'GET', + origin: '11.1.1.143', + destination: 'disney.com', + path: '/', + status: 311, + size: '35.24Kb', + type: 'application/text', + time: '256.71' +} + +export default class Logger extends React.Component { + + renderRow (item, i) { + console.log(item) + return ( + + {item.date} + {item.method} + {item.origin} + {item.destination} + {item.path} + {item.status} + {item.size} + {item.type} + {item.time} + +

+ + + + + + +

+ + + ) + } render () { return ( -
+
+ + + + + + + + + + + + + + + + + {Array.apply(null, Array(42)).map(() => { return logs }).map(this.renderRow)} + +
DateMethodOriginDestinationPathStatusSizeTypeTimeActions
) } From 0abfe3a5720b36283665b869d4ce141c50a3436c Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Mon, 20 Jun 2016 22:32:00 -0500 Subject: [PATCH 17/34] Fixed pagination --- app/components/NavigationBar/index.js | 38 +++++++++--------- app/components/Pagination/index.js | 39 +++++++++++++++++++ app/components/Pagination/messages.js | 8 ++++ app/components/Pagination/styles.css | 4 ++ app/components/Pagination/tests/index.test.js | 20 ++++++++++ app/containers/App/index.js | 7 +++- app/containers/App/styles.css | 5 +++ app/containers/Logger/index.js | 25 +++++------- app/containers/Logger/styles.css | 10 +++++ 9 files changed, 122 insertions(+), 34 deletions(-) create mode 100644 app/components/Pagination/index.js create mode 100644 app/components/Pagination/messages.js create mode 100644 app/components/Pagination/styles.css create mode 100644 app/components/Pagination/tests/index.test.js create mode 100644 app/containers/App/styles.css create mode 100644 app/containers/Logger/styles.css diff --git a/app/components/NavigationBar/index.js b/app/components/NavigationBar/index.js index 41bcf15..de365e0 100755 --- a/app/components/NavigationBar/index.js +++ b/app/components/NavigationBar/index.js @@ -10,24 +10,26 @@ import Logo from 'components/Icons/Logo' export default function NavigationBar () { return ( - +
+
+

+ + + + + +

+
+
+ + ) } diff --git a/app/components/Pagination/index.js b/app/components/Pagination/index.js new file mode 100644 index 0000000..6fdc223 --- /dev/null +++ b/app/components/Pagination/index.js @@ -0,0 +1,39 @@ +import React from 'react' + +import styles from './styles.css' + +export default function Pagination () { + return ( + + ) +} diff --git a/app/components/Pagination/messages.js b/app/components/Pagination/messages.js new file mode 100644 index 0000000..7833668 --- /dev/null +++ b/app/components/Pagination/messages.js @@ -0,0 +1,8 @@ +import { defineMessages } from 'react-intl' + +export default defineMessages({ + searchMessage: { + id: 'hyperfox.components.NavigationBar.search.message', + defaultMessage: 'Search.' + } +}) diff --git a/app/components/Pagination/styles.css b/app/components/Pagination/styles.css new file mode 100644 index 0000000..a7645ac --- /dev/null +++ b/app/components/Pagination/styles.css @@ -0,0 +1,4 @@ +.Pagination{ + background-color: #455a64; + padding: 10px; +} diff --git a/app/components/Pagination/tests/index.test.js b/app/components/Pagination/tests/index.test.js new file mode 100644 index 0000000..8c20525 --- /dev/null +++ b/app/components/Pagination/tests/index.test.js @@ -0,0 +1,20 @@ +/* Testing our NavigationBar component */ + +import NavigationBar from '../index' + +import Logo from 'components/Icons/Logo' +import styles from '../styles.css' + +import expect from 'expect' +import { shallow } from 'enzyme' +import React from 'react' + +describe('', () => { + it('should render the Logo', () => { + const navLogo = () + const renderedComponent = shallow( + + ) + expect(renderedComponent.contains(navLogo)).toEqual(true) + }) +}) diff --git a/app/containers/App/index.js b/app/containers/App/index.js index 4d1d8c3..49b069b 100755 --- a/app/containers/App/index.js +++ b/app/containers/App/index.js @@ -5,6 +5,10 @@ import React, {PropTypes} from 'react' import NavigationBar from 'components/NavigationBar' +import Pagination from 'components/Pagination' + +import classNames from 'classnames' +import styles from './styles.css' export default class App extends React.Component { static propTypes = { @@ -13,9 +17,10 @@ export default class App extends React.Component { render () { return ( -
+
{this.props.children} +
) } diff --git a/app/containers/App/styles.css b/app/containers/App/styles.css new file mode 100644 index 0000000..f622865 --- /dev/null +++ b/app/containers/App/styles.css @@ -0,0 +1,5 @@ +.App{ + height: 100vh; + display: flex; + flex-direction: column; +} diff --git a/app/containers/Logger/index.js b/app/containers/Logger/index.js index e552b11..2bd5637 100755 --- a/app/containers/Logger/index.js +++ b/app/containers/Logger/index.js @@ -1,9 +1,12 @@ /* Logger */ import React from 'react' -import Notification from 'components/Notification' -import messages from './messages' +import classNames from 'classnames' +import styles from './styles.css' +// import Notification from 'components/Notification' + +// import messages from './messages' const logs = { date: '12:51:12', @@ -48,17 +51,9 @@ export default class Logger extends React.Component { render () { return ( -
- - - - +
+
+ @@ -72,11 +67,11 @@ export default class Logger extends React.Component { - + {Array.apply(null, Array(42)).map(() => { return logs }).map(this.renderRow)}
Date MethodActions
-
+ ) } } diff --git a/app/containers/Logger/styles.css b/app/containers/Logger/styles.css new file mode 100644 index 0000000..335576f --- /dev/null +++ b/app/containers/Logger/styles.css @@ -0,0 +1,10 @@ +.Logger{ + flex: 1; + overflow: auto; + &__TableHead{ + background-color: #666; + } + &__TableBody{ + overflow: scroll; + } +} From e843899b1ef17030b99054593953fdd7fed4e9ec Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Tue, 21 Jun 2016 22:32:00 -0500 Subject: [PATCH 18/34] Create table component --- app/components/Table/TableBody.js | 19 +++++ app/components/Table/TableHeader.js | 29 ++++++++ app/components/Table/TableRow.js | 23 ++++++ app/components/Table/index.js | 65 +++++++++++++++++ app/containers/Logger/index.js | 108 +++++++++++----------------- 5 files changed, 176 insertions(+), 68 deletions(-) create mode 100644 app/components/Table/TableBody.js create mode 100644 app/components/Table/TableHeader.js create mode 100644 app/components/Table/TableRow.js create mode 100644 app/components/Table/index.js diff --git a/app/components/Table/TableBody.js b/app/components/Table/TableBody.js new file mode 100644 index 0000000..89fb443 --- /dev/null +++ b/app/components/Table/TableBody.js @@ -0,0 +1,19 @@ +/* TableBody */ + +import React from 'react' +import TableRow from './TableRow' + +export default class TableBody extends React.Component { + render () { + const columns = this.props.columns + const data = this.props.data + + return ( + + {data.map(function (item, idx) { + return + })} + + ) + } +} diff --git a/app/components/Table/TableHeader.js b/app/components/Table/TableHeader.js new file mode 100644 index 0000000..e52a54f --- /dev/null +++ b/app/components/Table/TableHeader.js @@ -0,0 +1,29 @@ +/* TableHeader */ + +import React from 'react' + +export default class TableHeader extends React.Component { + sort (column) { + return function (event) { + const sortDir = this.props.sortDir + this.props.onSort(column, sortDir) + }.bind(this) + } + + render () { + const columns = this.props.columns + const cell = function () { + return columns.map(function (c, i) { + return + {c} + + }, this) + }.bind(this) + + return ( + + {cell(this.props.item)} + + ) + } +} diff --git a/app/components/Table/TableRow.js b/app/components/Table/TableRow.js new file mode 100644 index 0000000..4b3ba3d --- /dev/null +++ b/app/components/Table/TableRow.js @@ -0,0 +1,23 @@ +/* TableRow */ + +import React from 'react' + +export default class TableRow extends React.Component { + render () { + const columns = this.props.columns + const data = this.props.data + const td = function (item) { + return columns.map(function (c, i) { + return + {item[c]} + + }, this) + }.bind(this) + + return ( + + {td(data)} + + ) + } +} diff --git a/app/components/Table/index.js b/app/components/Table/index.js new file mode 100644 index 0000000..249c870 --- /dev/null +++ b/app/components/Table/index.js @@ -0,0 +1,65 @@ +/* Table */ + +import React, {PropTypes} from 'react' +import TableHeader from './TableHeader' +import TableBody from './TableBody' + +export default class Table extends React.Component { + static propTypes = { + data: PropTypes.array + } + + constructor (props) { + super(props) + this.state = { + data: null, + sortDir: {} + } + this.sortByColumn = this.sortByColumn.bind(this) + this.sort = this.sort.bind(this) + } + + componentWillMount () { + this.setState({data: this.props.data}) + } + + getColumnNames () { + var firstEl = this.state.data[0] + return Object.keys(firstEl) + } + + sortByColumn (array, column, sortDir) { + return array.sort(function (a, b) { + var x = a[column] + var y = b[column] + if (sortDir === 'asc') { + return ((x > y) ? -1 : ((x < y) ? 1 : 0)) + } else { + return ((x < y) ? -1 : ((x > y) ? 1 : 0)) + } + }) + } + + sort (column) { + var sortDir = this.state.sortDir + var data = this.state.data + var sortedData = this.sortByColumn(data, column, sortDir[column]) + this.setState({data: sortedData}) + sortDir[column] = (sortDir[column] === 'asc' ? 'dsc' : 'asc') + this.setState({sortDir: sortDir}) + } + + render () { + var columns = this.getColumnNames() + var data = this.state.data + + return ( + + + + + +
+ ) + } +} diff --git a/app/containers/Logger/index.js b/app/containers/Logger/index.js index 2bd5637..c851893 100755 --- a/app/containers/Logger/index.js +++ b/app/containers/Logger/index.js @@ -1,77 +1,49 @@ /* Logger */ import React from 'react' +import Table from 'components/Table' -import classNames from 'classnames' import styles from './styles.css' -// import Notification from 'components/Notification' -// import messages from './messages' - -const logs = { - date: '12:51:12', - method: 'GET', - origin: '11.1.1.143', - destination: 'disney.com', - path: '/', - status: 311, - size: '35.24Kb', - type: 'application/text', - time: '256.71' -} - -export default class Logger extends React.Component { - - renderRow (item, i) { - console.log(item) - return ( - - {item.date} - {item.method} - {item.origin} - {item.destination} - {item.path} - {item.status} - {item.size} - {item.type} - {item.time} - -

- - - - - - -

- - - ) +const logs = [ + { + date: '12:51:12', + method: 'GET', + origin: '11.1.1.143', + destination: 'disney.com', + path: '/', + status: 311, + size: '35.24Kb', + type: 'application/text', + time: '256.71' + }, { + date: '12:51:12', + method: 'GET', + origin: '11.1.1.143', + destination: 'rog.mx', + path: '/', + status: 311, + size: '35.24Kb', + type: 'application/text', + time: '33.71' + }, { + date: '12:51:12', + method: 'GET', + origin: '11.1.1.143', + destination: 'test.mx', + path: '/', + status: 311, + size: '42.24Kb', + type: 'application/text', + time: '133.37' } +] - render () { - return ( -
- - - - - - - - - - - - - - - - - {Array.apply(null, Array(42)).map(() => { return logs }).map(this.renderRow)} - -
DateMethodOriginDestinationPathStatusSizeTypeTimeActions
-
- ) - } +export default function Logger () { + const data = Array.apply(null, Array(42)).map(() => { return logs[Math.floor(Math.random() * 3)] }) + return ( +
+ + + ) } From 0585724f459c36da5686dfe7d592000314b0cd5f Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Wed, 22 Jun 2016 22:32:00 -0500 Subject: [PATCH 19/34] Table func components --- app/components/Table/TableBody.js | 21 +++++++++------- app/components/Table/TableHeader.js | 39 +++++++++++++---------------- app/components/Table/TableRow.js | 32 ++++++++++++----------- 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/app/components/Table/TableBody.js b/app/components/Table/TableBody.js index 89fb443..c3306ff 100644 --- a/app/components/Table/TableBody.js +++ b/app/components/Table/TableBody.js @@ -1,19 +1,22 @@ /* TableBody */ -import React from 'react' +import React, {PropTypes} from 'react' import TableRow from './TableRow' -export default class TableBody extends React.Component { - render () { - const columns = this.props.columns - const data = this.props.data +export default function TableBody (props) { + const columns = props.columns + const data = props.data - return ( + return ( - {data.map(function (item, idx) { + {data.map((item, idx) => { return })} - ) - } + ) +} + +TableBody.propTypes = { + columns: PropTypes.array, + data: PropTypes.array } diff --git a/app/components/Table/TableHeader.js b/app/components/Table/TableHeader.js index e52a54f..bf733dd 100644 --- a/app/components/Table/TableHeader.js +++ b/app/components/Table/TableHeader.js @@ -1,29 +1,26 @@ /* TableHeader */ -import React from 'react' +import React, {PropTypes} from 'react' -export default class TableHeader extends React.Component { - sort (column) { - return function (event) { - const sortDir = this.props.sortDir - this.props.onSort(column, sortDir) - }.bind(this) +export default function TableHeader (props) { + const columns = props.columns + const sort = (column) => { + return (event) => { + const sortDir = props.sortDir + props.onSort(column, sortDir) + } } - render () { - const columns = this.props.columns - const cell = function () { - return columns.map(function (c, i) { - return - }, this) - }.bind(this) - - return ( + return ( - {cell(this.props.item)} + {columns.map((c, i) => { + return + })} - ) - } + ) +} + +TableHeader.propTypes = { + columns: PropTypes.array, + sortDir: PropTypes.func } diff --git a/app/components/Table/TableRow.js b/app/components/Table/TableRow.js index 4b3ba3d..9108c52 100644 --- a/app/components/Table/TableRow.js +++ b/app/components/Table/TableRow.js @@ -1,23 +1,25 @@ /* TableRow */ -import React from 'react' +import React, {PropTypes} from 'react' -export default class TableRow extends React.Component { - render () { - const columns = this.props.columns - const data = this.props.data - const td = function (item) { - return columns.map(function (c, i) { - return - }, this) - }.bind(this) +export default function TableRow (props) { + const columns = props.columns + const data = props.data - return ( + const td = (item) => { + return columns.map((c, i) => { + return + }) + } + + return ( {td(data)} - ) - } + ) +} + +TableRow.propTypes = { + columns: PropTypes.array, + data: PropTypes.object } From c3e375866aab8bc4d188daa203eef648e2072400 Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Thu, 23 Jun 2016 22:32:00 -0500 Subject: [PATCH 20/34] Fix dll plugin --- internals/config.js | 3 ++- package.json | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/internals/config.js b/internals/config.js index 87ae811..1c87061 100755 --- a/internals/config.js +++ b/internals/config.js @@ -26,7 +26,8 @@ const HyperfoxLive = { 'cross-env', 'express', 'minimist', - 'sanitize.css' + 'sanitize.css', + 'bulma' ], /** diff --git a/package.json b/package.json index ee362ea..a40dd91 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "babel-polyfill": "^6.7.4", "bulma": "0.0.28", "chalk": "^1.1.3", + "classnames": "^2.2.5", "compression": "^1.6.1", "express": "^4.13.4", "fontfaceobserver": "^1.7.1", From fab608f8a7a3c0be3aa34a61f2aca6216d2fbe88 Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Thu, 23 Jun 2016 22:32:00 -0500 Subject: [PATCH 21/34] Add table styles --- app/components/Table/TableBody.js | 5 +++-- app/components/Table/index.js | 9 ++++++--- app/components/Table/styles.css | 9 +++++++++ app/containers/Logger/index.js | 2 +- app/containers/Logger/styles.css | 6 ------ 5 files changed, 19 insertions(+), 12 deletions(-) create mode 100644 app/components/Table/styles.css diff --git a/app/components/Table/TableBody.js b/app/components/Table/TableBody.js index c3306ff..7ff209b 100644 --- a/app/components/Table/TableBody.js +++ b/app/components/Table/TableBody.js @@ -8,7 +8,7 @@ export default function TableBody (props) { const data = props.data return ( - + {data.map((item, idx) => { return })} @@ -18,5 +18,6 @@ export default function TableBody (props) { TableBody.propTypes = { columns: PropTypes.array, - data: PropTypes.array + data: PropTypes.array, + className: PropTypes.string } diff --git a/app/components/Table/index.js b/app/components/Table/index.js index 249c870..4e85647 100644 --- a/app/components/Table/index.js +++ b/app/components/Table/index.js @@ -4,6 +4,9 @@ import React, {PropTypes} from 'react' import TableHeader from './TableHeader' import TableBody from './TableBody' +import styles from './styles.css' +import classNames from 'classnames' + export default class Table extends React.Component { static propTypes = { data: PropTypes.array @@ -54,11 +57,11 @@ export default class Table extends React.Component { var data = this.state.data return ( -
- {c} -
{c}
- {item[c]} - {item[c]}
- +
+ - +
) } diff --git a/app/components/Table/styles.css b/app/components/Table/styles.css new file mode 100644 index 0000000..9177254 --- /dev/null +++ b/app/components/Table/styles.css @@ -0,0 +1,9 @@ +.Table{ + table-layout: fixed; + &__TableHead{ + background-color: #666; + } + &__TableBody{ + overflow: scroll; + } +} diff --git a/app/containers/Logger/index.js b/app/containers/Logger/index.js index c851893..6ec8946 100755 --- a/app/containers/Logger/index.js +++ b/app/containers/Logger/index.js @@ -19,7 +19,7 @@ const logs = [ }, { date: '12:51:12', method: 'GET', - origin: '11.1.1.143', + origin: '11.1.1.13', destination: 'rog.mx', path: '/', status: 311, diff --git a/app/containers/Logger/styles.css b/app/containers/Logger/styles.css index 335576f..99e08bb 100644 --- a/app/containers/Logger/styles.css +++ b/app/containers/Logger/styles.css @@ -1,10 +1,4 @@ .Logger{ flex: 1; overflow: auto; - &__TableHead{ - background-color: #666; - } - &__TableBody{ - overflow: scroll; - } } From 42227e70a624006380207723509cc8dc69fa13be Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Fri, 24 Jun 2016 22:32:00 -0500 Subject: [PATCH 22/34] Add translations generator --- app/app.js | 6 ++ app/translations/en.json | 8 +- app/translations/es.json | 14 ++- internals/scripts/getTranslations.js | 148 +++++++++++++++++++++++++++ package.json | 5 +- 5 files changed, 174 insertions(+), 7 deletions(-) create mode 100644 internals/scripts/getTranslations.js diff --git a/app/app.js b/app/app.js index ab751b3..5e89209 100755 --- a/app/app.js +++ b/app/app.js @@ -60,6 +60,12 @@ const render = () => { document.getElementById('app') ) } +// Hot reloadable translation json files +if (module.hot) { + module.hot.accept('./i18n', () => { + render(translationMessages) + }) +} // Chunked polyfill for browsers without Intl support if (!window.Intl) { diff --git a/app/translations/en.json b/app/translations/en.json index 18df2ae..b28617a 100755 --- a/app/translations/en.json +++ b/app/translations/en.json @@ -1,17 +1,17 @@ [ { "id": "hyperfox.components.NavigationBar.search.message", - "defaultMessage": "Search", - "message": "Search" + "defaultMessage": "Search.", + "message": "" }, { "id": "hyperfox.containers.Logger.Notification.noconnected.message", "defaultMessage": "Could not connect to the Hyperfox API. Seems like hyperfox is not running on your local box.", - "message": "Could not connect to the Hyperfox API. Seems like hyperfox is not running on your local box." + "message": "" }, { "id": "hyperfox.containers.Logger.Notification.nodata.message", "defaultMessage": "No data to show yet.", - "message": "No data to show yet." + "message": "" } ] diff --git a/app/translations/es.json b/app/translations/es.json index 660cf50..7038803 100755 --- a/app/translations/es.json +++ b/app/translations/es.json @@ -1,7 +1,17 @@ [ { "id": "hyperfox.components.NavigationBar.search.message", - "defaultMessage": "Buscar", + "defaultMessage": "Search.", "message": "Buscar" + }, + { + "id": "hyperfox.containers.Logger.Notification.noconnected.message", + "defaultMessage": "Could not connect to the Hyperfox API. Seems like hyperfox is not running on your local box.", + "message": "" + }, + { + "id": "hyperfox.containers.Logger.Notification.nodata.message", + "defaultMessage": "No data to show yet.", + "message": "" } -] +] \ No newline at end of file diff --git a/internals/scripts/getTranslations.js b/internals/scripts/getTranslations.js new file mode 100644 index 0000000..7d3e8f6 --- /dev/null +++ b/internals/scripts/getTranslations.js @@ -0,0 +1,148 @@ +/** + * This script will extract the internationalization messages from all components + and package them in the transalation json files in the translations file. + */ +const fs = require('fs'); +const nodeGlob = require('glob'); +const chalk = require('chalk'); +const transform = require('babel-core').transform; +const pkg = require('../../package.json'); +const i18n = require('../../app/i18n'); + +require('shelljs/global'); + +// Glob to match all js files except test files +const FILES_TO_PARSE = 'app/**/!(*.test).js'; +const locales = i18n.appLocales; + +// Wrap async functions below into a promise +const glob = (pattern) => new Promise((resolve, reject) => { + nodeGlob(pattern, (error, value) => (error ? reject(error) : resolve(value))); +}); + +const readFile = (fileName) => new Promise((resolve, reject) => { + fs.readFile(fileName, (error, value) => (error ? reject(error) : resolve(value))); +}); + +const writeFile = (fileName, data) => new Promise((resolve, reject) => { + fs.writeFile(fileName, data, (error, value) => (error ? reject(error) : resolve(value))); +}); + +// Helper function to log a gray dividing line +const logDivider = () => { + console.log( + chalk.gray('------------------------------------------------------------------------') + ); +}; + +// Helper function to log an error in bold red +const logError = (error, ...args) => { + console.error( + chalk.bold.red(error), + ...args + ); +}; + +// Helper function to log a success message in bold green +const logSuccess = (success, ...args) => { + console.log( + chalk.green(success), + ...args + ); +}; + +// Store existing translations into memory +const oldLocaleMappings = []; +const localeMappings = []; +// Loop to run once per locale +for (const locale of locales) { + oldLocaleMappings[locale] = {}; + localeMappings[locale] = {}; + // File to store translation messages into + const translationFileName = `app/translations/${locale}.json`; + try { + // Parse the old translation message JSON files + const messages = JSON.parse(fs.readFileSync(translationFileName)); + for (const message of messages) { + oldLocaleMappings[locale][message.id] = message; + } + } catch (error) { + if (error.code !== 'ENOENT') { + logError(`There was an error loading this translation file: ${translationFileName}\n${error}`); + } + } +} + + +const extractFromFile = async (fileName) => { + try { + const code = await readFile(fileName); + // Use babel plugin to extract instances where react-intl is used + const { metadata: result } = await transform(code, { + presets: pkg.babel.presets, + plugins: [ + ['react-intl'], + ], + }); + for (const message of result['react-intl'].messages) { + for (const locale of locales) { + const oldLocaleMapping = oldLocaleMappings[locale][message.id]; + // Merge old translations into the babel extracted instances where react-intl is used + localeMappings[locale][message.id] = { + id: message.id, + description: message.description, + defaultMessage: message.defaultMessage, + message: (oldLocaleMapping && oldLocaleMapping.message) ? oldLocaleMapping.message : '', + }; + } + } + } catch (error) { + logError(`There was an error transforming this file: ${fileName}\n${error}`); + } +}; + +(async function main() { + const files = await glob(FILES_TO_PARSE); + + // Run extraction on all files that match the glob on line 16 + await Promise.all( + files.map((fileName) => extractFromFile(fileName)) + ); + + // Make the directory if it doesn't exist, especially for first run + mkdir('-p', 'app/translations'); + logDivider(); + for (const locale of locales) { + const translationFileName = `app/translations/${locale}.json`; + try { + // Sort the translation JSON file so that git diffing is easier + // Otherwise the translation messages will jump around every time we extract + let messages = Object.values(localeMappings[locale]).sort((a, b) => { + a = a.id.toUpperCase(); + b = b.id.toUpperCase(); + if (a < b) { + return -1; + } else if (a > b) { + return 1; + } else { + return 0; + } + }); + // Write to file the JSON representation of the translation messages + await writeFile( + translationFileName, + JSON.stringify( + messages, + null, + 2 + ) + ); + + logSuccess(`Translation file for ${locale} successfully saved to: ${translationFileName}`); + } catch (error) { + logError(`There was an error saving this translation file: ${translationFileName}\n${error}`); + } + } + + logDivider(); +}()); diff --git a/package.json b/package.json index a40dd91..5304a4b 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ }, "scripts": { "postinstall": "npm run build:dll", + "intl": "babel-node --presets es2015 -- ./internals/scripts/getTranslations.js", "prebuild": "npm run test && npm run build:clean", "build": "cross-env NODE_ENV=production webpack --config internals/webpack/webpack.prod.babel.js --color -p", "build:clean": "rimraf ./build/*", @@ -52,7 +53,8 @@ "cross-env", "express", "minimist", - "sanitize.css" + "sanitize.css", + "bulma" ], "include": [ "core-js", @@ -87,6 +89,7 @@ "whatwg-fetch": "^1.0.0" }, "devDependencies": { + "babel-cli": "^6.10.1", "babel-core": "^6.7.7", "babel-eslint": "^6.0.5", "babel-loader": "^6.2.4", From 81f0a596414478298e136ce439b8e0e937c4b621 Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Sat, 25 Jun 2016 22:32:00 -0500 Subject: [PATCH 23/34] Electron integration and update dependencies --- __html/.bowerrc | 3 - __html/.editorconfig | 21 - __html/.gitattributes | 1 - __html/.gitignore | 6 - __html/.jshintrc | 23 - __html/.travis.yml | 6 - __html/Gruntfile.js | 441 -------------- __html/Makefile | 6 - __html/app/.buildignore | 1 - __html/app/.htaccess | 543 ------------------ __html/app/favicon.ico | Bin 6782 -> 0 bytes __html/app/images/logo.svg | 50 -- __html/app/index.html | 118 ---- __html/app/scripts/app.js | 49 -- __html/app/scripts/controllers/main.js | 142 ----- __html/app/scripts/services/main.js | 62 -- __html/app/styles/main.scss | 197 ------- __html/app/views/details.html | 70 --- __html/app/views/main.html | 108 ---- __html/bower.json | 22 - __html/package.json | 44 -- __html/test/.jshintrc | 36 -- __html/test/karma.conf.js | 75 --- __html/test/spec/controllers/about.js | 22 - __html/test/spec/controllers/main.js | 22 - .../NavigationBar/tests/index.test.js | 2 +- app/components/Pagination/tests/index.test.js | 17 +- electron/main.js | 32 ++ internals/scripts/getTranslations.js | 124 ++-- package.json | 133 ++--- 30 files changed, 158 insertions(+), 2218 deletions(-) delete mode 100644 __html/.bowerrc delete mode 100644 __html/.editorconfig delete mode 100644 __html/.gitattributes delete mode 100644 __html/.gitignore delete mode 100644 __html/.jshintrc delete mode 100644 __html/.travis.yml delete mode 100644 __html/Gruntfile.js delete mode 100644 __html/Makefile delete mode 100644 __html/app/.buildignore delete mode 100644 __html/app/.htaccess delete mode 100644 __html/app/favicon.ico delete mode 100644 __html/app/images/logo.svg delete mode 100644 __html/app/index.html delete mode 100644 __html/app/scripts/app.js delete mode 100644 __html/app/scripts/controllers/main.js delete mode 100644 __html/app/scripts/services/main.js delete mode 100644 __html/app/styles/main.scss delete mode 100644 __html/app/views/details.html delete mode 100644 __html/app/views/main.html delete mode 100644 __html/bower.json delete mode 100644 __html/package.json delete mode 100644 __html/test/.jshintrc delete mode 100644 __html/test/karma.conf.js delete mode 100644 __html/test/spec/controllers/about.js delete mode 100644 __html/test/spec/controllers/main.js create mode 100644 electron/main.js diff --git a/__html/.bowerrc b/__html/.bowerrc deleted file mode 100644 index 69fad35..0000000 --- a/__html/.bowerrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "directory": "bower_components" -} diff --git a/__html/.editorconfig b/__html/.editorconfig deleted file mode 100644 index c2cdfb8..0000000 --- a/__html/.editorconfig +++ /dev/null @@ -1,21 +0,0 @@ -# EditorConfig helps developers define and maintain consistent -# coding styles between different editors and IDEs -# editorconfig.org - -root = true - - -[*] - -# Change these settings to your own preference -indent_style = space -indent_size = 2 - -# We recommend you to keep these unchanged -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true - -[*.md] -trim_trailing_whitespace = false diff --git a/__html/.gitattributes b/__html/.gitattributes deleted file mode 100644 index 2125666..0000000 --- a/__html/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -* text=auto \ No newline at end of file diff --git a/__html/.gitignore b/__html/.gitignore deleted file mode 100644 index 980a1aa..0000000 --- a/__html/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -node_modules -*.swp -dist -.tmp -.sass-cache -bower_components diff --git a/__html/.jshintrc b/__html/.jshintrc deleted file mode 100644 index f750969..0000000 --- a/__html/.jshintrc +++ /dev/null @@ -1,23 +0,0 @@ -{ - "node": true, - "browser": true, - "esnext": true, - "bitwise": true, - "camelcase": true, - "curly": true, - "eqeqeq": true, - "immed": true, - "indent": 2, - "latedef": true, - "newcap": true, - "noarg": true, - "quotmark": "single", - "undef": true, - "unused": true, - "strict": true, - "trailing": true, - "smarttabs": true, - "globals": { - "angular": false - } -} diff --git a/__html/.travis.yml b/__html/.travis.yml deleted file mode 100644 index a80b6e0..0000000 --- a/__html/.travis.yml +++ /dev/null @@ -1,6 +0,0 @@ -language: node_js -node_js: - - '0.10' -before_script: - - 'npm install -g bower grunt-cli' - - 'bower install' diff --git a/__html/Gruntfile.js b/__html/Gruntfile.js deleted file mode 100644 index 737d49a..0000000 --- a/__html/Gruntfile.js +++ /dev/null @@ -1,441 +0,0 @@ -// Generated on 2014-12-20 using generator-angular 0.10.0 -'use strict'; - -// # Globbing -// for performance reasons we're only matching one level down: -// 'test/spec/{,*/}*.js' -// use this if you want to recursively match all subfolders: -// 'test/spec/**/*.js' - -module.exports = function (grunt) { - - // Load grunt tasks automatically - require('load-grunt-tasks')(grunt); - - // Time how long tasks take. Can help when optimizing build times - require('time-grunt')(grunt); - - // Configurable paths for the application - var appConfig = { - app: require('./bower.json').appPath || 'app', - dist: 'dist' - }; - - // Define the configuration for all the tasks - grunt.initConfig({ - - // Project settings - yeoman: appConfig, - - // Watches files for changes and runs tasks based on the changed files - watch: { - bower: { - files: ['bower.json'], - tasks: ['wiredep'] - }, - js: { - files: ['<%= yeoman.app %>/scripts/{,*/}*.js'], - tasks: ['newer:jshint:all'], - options: { - livereload: '<%= connect.options.livereload %>' - } - }, - jsTest: { - files: ['test/spec/{,*/}*.js'], - tasks: ['newer:jshint:test', 'karma'] - }, - compass: { - files: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'], - tasks: ['compass:server', 'autoprefixer'] - }, - gruntfile: { - files: ['Gruntfile.js'] - }, - livereload: { - options: { - livereload: '<%= connect.options.livereload %>' - }, - files: [ - '<%= yeoman.app %>/{,*/}*.html', - '.tmp/styles/{,*/}*.css', - '<%= yeoman.app %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}' - ] - } - }, - - // The actual grunt server settings - connect: { - options: { - port: 9000, - // Change this to '0.0.0.0' to access the server from outside. - hostname: 'localhost', - livereload: 35729 - }, - livereload: { - options: { - open: true, - middleware: function (connect) { - return [ - connect.static('.tmp'), - connect().use( - '/bower_components', - connect.static('./bower_components') - ), - connect.static(appConfig.app) - ]; - } - } - }, - test: { - options: { - port: 9001, - middleware: function (connect) { - return [ - connect.static('.tmp'), - connect.static('test'), - connect().use( - '/bower_components', - connect.static('./bower_components') - ), - connect.static(appConfig.app) - ]; - } - } - }, - dist: { - options: { - open: true, - base: '<%= yeoman.dist %>' - } - } - }, - - // Make sure code styles are up to par and there are no obvious mistakes - jshint: { - options: { - jshintrc: '.jshintrc', - reporter: require('jshint-stylish') - }, - all: { - src: [ - 'Gruntfile.js', - '<%= yeoman.app %>/scripts/{,*/}*.js' - ] - }, - test: { - options: { - jshintrc: 'test/.jshintrc' - }, - src: ['test/spec/{,*/}*.js'] - } - }, - - // Empties folders to start fresh - clean: { - dist: { - files: [{ - dot: true, - src: [ - '.tmp', - '<%= yeoman.dist %>/{,*/}*', - '!<%= yeoman.dist %>/.git{,*/}*' - ] - }] - }, - server: '.tmp' - }, - - // Add vendor prefixed styles - autoprefixer: { - options: { - browsers: ['last 1 version'] - }, - dist: { - files: [{ - expand: true, - cwd: '.tmp/styles/', - src: '{,*/}*.css', - dest: '.tmp/styles/' - }] - } - }, - - // Automatically inject Bower components into the app - wiredep: { - app: { - src: ['<%= yeoman.app %>/index.html'], - ignorePath: /\.\.\// - }, - sass: { - src: ['<%= yeoman.app %>/styles/{,*/}*.{scss,sass}'], - ignorePath: /(\.\.\/){1,2}bower_components\// - } - }, - - // Compiles Sass to CSS and generates necessary files if requested - compass: { - options: { - sassDir: '<%= yeoman.app %>/styles', - cssDir: '.tmp/styles', - generatedImagesDir: '.tmp/images/generated', - imagesDir: '<%= yeoman.app %>/images', - javascriptsDir: '<%= yeoman.app %>/scripts', - fontsDir: '<%= yeoman.app %>/styles/fonts', - importPath: './bower_components', - httpImagesPath: '/images', - httpGeneratedImagesPath: '/images/generated', - httpFontsPath: '/styles/fonts', - relativeAssets: false, - assetCacheBuster: false, - raw: 'Sass::Script::Number.precision = 10\n' - }, - dist: { - options: { - generatedImagesDir: '<%= yeoman.dist %>/images/generated' - } - }, - server: { - options: { - debugInfo: true - } - } - }, - - // Renames files for browser caching purposes - filerev: { - dist: { - src: [ - '<%= yeoman.dist %>/scripts/{,*/}*.js', - '<%= yeoman.dist %>/styles/{,*/}*.css', - '<%= yeoman.dist %>/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}', - '<%= yeoman.dist %>/styles/fonts/*' - ] - } - }, - - // Reads HTML for usemin blocks to enable smart builds that automatically - // concat, minify and revision files. Creates configurations in memory so - // additional tasks can operate on them - useminPrepare: { - html: '<%= yeoman.app %>/index.html', - options: { - dest: '<%= yeoman.dist %>', - flow: { - html: { - steps: { - js: ['concat', 'uglifyjs'], - css: ['cssmin'] - }, - post: {} - } - } - } - }, - - // Performs rewrites based on filerev and the useminPrepare configuration - usemin: { - html: ['<%= yeoman.dist %>/{,*/}*.html'], - css: ['<%= yeoman.dist %>/styles/{,*/}*.css'], - options: { - assetsDirs: ['<%= yeoman.dist %>','<%= yeoman.dist %>/images'] - } - }, - - // The following *-min tasks will produce minified files in the dist folder - // By default, your `index.html`'s will take care of - // minification. These next options are pre-configured if you do not wish - // to use the Usemin blocks. - // cssmin: { - // dist: { - // files: { - // '<%= yeoman.dist %>/styles/main.css': [ - // '.tmp/styles/{,*/}*.css' - // ] - // } - // } - // }, - // uglify: { - // dist: { - // files: { - // '<%= yeoman.dist %>/scripts/scripts.js': [ - // '<%= yeoman.dist %>/scripts/scripts.js' - // ] - // } - // } - // }, - // concat: { - // dist: {} - // }, - - imagemin: { - dist: { - files: [{ - expand: true, - cwd: '<%= yeoman.app %>/images', - src: '{,*/}*.{png,jpg,jpeg,gif}', - dest: '<%= yeoman.dist %>/images' - }] - } - }, - - svgmin: { - dist: { - files: [{ - expand: true, - cwd: '<%= yeoman.app %>/images', - src: '{,*/}*.svg', - dest: '<%= yeoman.dist %>/images' - }] - } - }, - - htmlmin: { - dist: { - options: { - collapseWhitespace: true, - conservativeCollapse: true, - collapseBooleanAttributes: true, - removeCommentsFromCDATA: true, - removeOptionalTags: true - }, - files: [{ - expand: true, - cwd: '<%= yeoman.dist %>', - src: ['*.html', 'views/{,*/}*.html'], - dest: '<%= yeoman.dist %>' - }] - } - }, - - // ng-annotate tries to make the code safe for minification automatically - // by using the Angular long form for dependency injection. - ngAnnotate: { - dist: { - files: [{ - expand: true, - cwd: '.tmp/concat/scripts', - src: ['*.js', '!oldieshim.js'], - dest: '.tmp/concat/scripts' - }] - } - }, - - // Replace Google CDN references - cdnify: { - dist: { - html: ['<%= yeoman.dist %>/*.html'] - } - }, - - // Copies remaining files to places other tasks can use - copy: { - dist: { - files: [{ - expand: true, - dot: true, - cwd: '<%= yeoman.app %>', - dest: '<%= yeoman.dist %>', - src: [ - '*.{ico,png,txt}', - '.htaccess', - '*.html', - 'views/{,*/}*.html', - 'images/{,*/}*.{webp}', - 'fonts/{,*/}*.*' - ] - }, { - expand: true, - cwd: '.tmp/images', - dest: '<%= yeoman.dist %>/images', - src: ['generated/*'] - }, { - expand: true, - cwd: '.', - src: 'bower_components/bootstrap-sass-official/assets/fonts/bootstrap/*', - dest: '<%= yeoman.dist %>' - }] - }, - styles: { - expand: true, - cwd: '<%= yeoman.app %>/styles', - dest: '.tmp/styles/', - src: '{,*/}*.css' - } - }, - - // Run some tasks in parallel to speed up the build process - concurrent: { - server: [ - 'compass:server' - ], - test: [ - 'compass' - ], - dist: [ - 'compass:dist', - 'imagemin', - 'svgmin' - ] - }, - - // Test settings - karma: { - unit: { - configFile: 'test/karma.conf.js', - singleRun: true - } - } - }); - - - grunt.registerTask('serve', 'Compile then start a connect web server', function (target) { - if (target === 'dist') { - return grunt.task.run(['build', 'connect:dist:keepalive']); - } - - grunt.task.run([ - 'clean:server', - 'wiredep', - 'concurrent:server', - 'autoprefixer', - 'connect:livereload', - 'watch' - ]); - }); - - grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) { - grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.'); - grunt.task.run(['serve:' + target]); - }); - - grunt.registerTask('test', [ - 'clean:server', - 'concurrent:test', - 'autoprefixer', - 'connect:test', - 'karma' - ]); - - grunt.registerTask('build', [ - 'clean:dist', - 'wiredep', - 'useminPrepare', - 'concurrent:dist', - 'autoprefixer', - 'concat', - 'ngAnnotate', - 'copy:dist', - 'cdnify', - 'cssmin', - 'uglify', - 'filerev', - 'usemin', - 'htmlmin' - ]); - - grunt.registerTask('default', [ - 'newer:jshint', - 'test', - 'build' - ]); -}; diff --git a/__html/Makefile b/__html/Makefile deleted file mode 100644 index 64337a5..0000000 --- a/__html/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -clean: - grunt clean - -publish: clean - grunt build - scp -r dist/* www-data@hyperfox.org:/var/www/hyperfox.org/live/ diff --git a/__html/app/.buildignore b/__html/app/.buildignore deleted file mode 100644 index fc98b8e..0000000 --- a/__html/app/.buildignore +++ /dev/null @@ -1 +0,0 @@ -*.coffee \ No newline at end of file diff --git a/__html/app/.htaccess b/__html/app/.htaccess deleted file mode 100644 index cb84cb9..0000000 --- a/__html/app/.htaccess +++ /dev/null @@ -1,543 +0,0 @@ -# Apache Configuration File - -# (!) Using `.htaccess` files slows down Apache, therefore, if you have access -# to the main server config file (usually called `httpd.conf`), you should add -# this logic there: http://httpd.apache.org/docs/current/howto/htaccess.html. - -# ############################################################################## -# # CROSS-ORIGIN RESOURCE SHARING (CORS) # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | Cross-domain AJAX requests | -# ------------------------------------------------------------------------------ - -# Enable cross-origin AJAX requests. -# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity -# http://enable-cors.org/ - -# -# Header set Access-Control-Allow-Origin "*" -# - -# ------------------------------------------------------------------------------ -# | CORS-enabled images | -# ------------------------------------------------------------------------------ - -# Send the CORS header for images when browsers request it. -# https://developer.mozilla.org/en/CORS_Enabled_Image -# http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html -# http://hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/ - - - - - SetEnvIf Origin ":" IS_CORS - Header set Access-Control-Allow-Origin "*" env=IS_CORS - - - - -# ------------------------------------------------------------------------------ -# | Web fonts access | -# ------------------------------------------------------------------------------ - -# Allow access from all domains for web fonts - - - - Header set Access-Control-Allow-Origin "*" - - - - -# ############################################################################## -# # ERRORS # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | 404 error prevention for non-existing redirected folders | -# ------------------------------------------------------------------------------ - -# Prevent Apache from returning a 404 error for a rewrite if a directory -# with the same name does not exist. -# http://httpd.apache.org/docs/current/content-negotiation.html#multiviews -# http://www.webmasterworld.com/apache/3808792.htm - -Options -MultiViews - -# ------------------------------------------------------------------------------ -# | Custom error messages / pages | -# ------------------------------------------------------------------------------ - -# You can customize what Apache returns to the client in case of an error (see -# http://httpd.apache.org/docs/current/mod/core.html#errordocument), e.g.: - -ErrorDocument 404 /404.html - - -# ############################################################################## -# # INTERNET EXPLORER # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | Better website experience | -# ------------------------------------------------------------------------------ - -# Force IE to render pages in the highest available mode in the various -# cases when it may not: http://hsivonen.iki.fi/doctype/ie-mode.pdf. - - - Header set X-UA-Compatible "IE=edge" - # `mod_headers` can't match based on the content-type, however, we only - # want to send this header for HTML pages and not for the other resources - - Header unset X-UA-Compatible - - - -# ------------------------------------------------------------------------------ -# | Cookie setting from iframes | -# ------------------------------------------------------------------------------ - -# Allow cookies to be set from iframes in IE. - -# -# Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"" -# - -# ------------------------------------------------------------------------------ -# | Screen flicker | -# ------------------------------------------------------------------------------ - -# Stop screen flicker in IE on CSS rollovers (this only works in -# combination with the `ExpiresByType` directives for images from below). - -# BrowserMatch "MSIE" brokenvary=1 -# BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1 -# BrowserMatch "Opera" !brokenvary -# SetEnvIf brokenvary 1 force-no-vary - - -# ############################################################################## -# # MIME TYPES AND ENCODING # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | Proper MIME types for all files | -# ------------------------------------------------------------------------------ - - - - # Audio - AddType audio/mp4 m4a f4a f4b - AddType audio/ogg oga ogg - - # JavaScript - # Normalize to standard type (it's sniffed in IE anyways): - # http://tools.ietf.org/html/rfc4329#section-7.2 - AddType application/javascript js jsonp - AddType application/json json - - # Video - AddType video/mp4 mp4 m4v f4v f4p - AddType video/ogg ogv - AddType video/webm webm - AddType video/x-flv flv - - # Web fonts - AddType application/font-woff woff - AddType application/vnd.ms-fontobject eot - - # Browsers usually ignore the font MIME types and sniff the content, - # however, Chrome shows a warning if other MIME types are used for the - # following fonts. - AddType application/x-font-ttf ttc ttf - AddType font/opentype otf - - # Make SVGZ fonts work on iPad: - # https://twitter.com/FontSquirrel/status/14855840545 - AddType image/svg+xml svg svgz - AddEncoding gzip svgz - - # Other - AddType application/octet-stream safariextz - AddType application/x-chrome-extension crx - AddType application/x-opera-extension oex - AddType application/x-shockwave-flash swf - AddType application/x-web-app-manifest+json webapp - AddType application/x-xpinstall xpi - AddType application/xml atom rdf rss xml - AddType image/webp webp - AddType image/x-icon ico - AddType text/cache-manifest appcache manifest - AddType text/vtt vtt - AddType text/x-component htc - AddType text/x-vcard vcf - - - -# ------------------------------------------------------------------------------ -# | UTF-8 encoding | -# ------------------------------------------------------------------------------ - -# Use UTF-8 encoding for anything served as `text/html` or `text/plain`. -AddDefaultCharset utf-8 - -# Force UTF-8 for certain file formats. - - AddCharset utf-8 .atom .css .js .json .rss .vtt .webapp .xml - - - -# ############################################################################## -# # URL REWRITES # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | Rewrite engine | -# ------------------------------------------------------------------------------ - -# Turning on the rewrite engine and enabling the `FollowSymLinks` option is -# necessary for the following directives to work. - -# If your web host doesn't allow the `FollowSymlinks` option, you may need to -# comment it out and use `Options +SymLinksIfOwnerMatch` but, be aware of the -# performance impact: http://httpd.apache.org/docs/current/misc/perf-tuning.html#symlinks - -# Also, some cloud hosting services require `RewriteBase` to be set: -# http://www.rackspace.com/knowledge_center/frequently-asked-question/why-is-mod-rewrite-not-working-on-my-site - - - Options +FollowSymlinks - # Options +SymLinksIfOwnerMatch - RewriteEngine On - # RewriteBase / - - -# ------------------------------------------------------------------------------ -# | Suppressing / Forcing the "www." at the beginning of URLs | -# ------------------------------------------------------------------------------ - -# The same content should never be available under two different URLs especially -# not with and without "www." at the beginning. This can cause SEO problems -# (duplicate content), therefore, you should choose one of the alternatives and -# redirect the other one. - -# By default option 1 (no "www.") is activated: -# http://no-www.org/faq.php?q=class_b - -# If you'd prefer to use option 2, just comment out all the lines from option 1 -# and uncomment the ones from option 2. - -# IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME! - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Option 1: rewrite www.example.com → example.com - - - RewriteCond %{HTTPS} !=on - RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] - RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L] - - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Option 2: rewrite example.com → www.example.com - -# Be aware that the following might not be a good idea if you use "real" -# subdomains for certain parts of your website. - -# -# RewriteCond %{HTTPS} !=on -# RewriteCond %{HTTP_HOST} !^www\..+$ [NC] -# RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L] -# - - -# ############################################################################## -# # SECURITY # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | Content Security Policy (CSP) | -# ------------------------------------------------------------------------------ - -# You can mitigate the risk of cross-site scripting and other content-injection -# attacks by setting a Content Security Policy which whitelists trusted sources -# of content for your site. - -# The example header below allows ONLY scripts that are loaded from the current -# site's origin (no inline scripts, no CDN, etc). This almost certainly won't -# work as-is for your site! - -# To get all the details you'll need to craft a reasonable policy for your site, -# read: http://html5rocks.com/en/tutorials/security/content-security-policy (or -# see the specification: http://w3.org/TR/CSP). - -# -# Header set Content-Security-Policy "script-src 'self'; object-src 'self'" -# -# Header unset Content-Security-Policy -# -# - -# ------------------------------------------------------------------------------ -# | File access | -# ------------------------------------------------------------------------------ - -# Block access to directories without a default document. -# Usually you should leave this uncommented because you shouldn't allow anyone -# to surf through every directory on your server (which may includes rather -# private places like the CMS's directories). - - - Options -Indexes - - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Block access to hidden files and directories. -# This includes directories used by version control systems such as Git and SVN. - - - RewriteCond %{SCRIPT_FILENAME} -d [OR] - RewriteCond %{SCRIPT_FILENAME} -f - RewriteRule "(^|/)\." - [F] - - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Block access to backup and source files. -# These files may be left by some text editors and can pose a great security -# danger when anyone has access to them. - - - Order allow,deny - Deny from all - Satisfy All - - -# ------------------------------------------------------------------------------ -# | Secure Sockets Layer (SSL) | -# ------------------------------------------------------------------------------ - -# Rewrite secure requests properly to prevent SSL certificate warnings, e.g.: -# prevent `https://www.example.com` when your certificate only allows -# `https://secure.example.com`. - -# -# RewriteCond %{SERVER_PORT} !^443 -# RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L] -# - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Force client-side SSL redirection. - -# If a user types "example.com" in his browser, the above rule will redirect him -# to the secure version of the site. That still leaves a window of opportunity -# (the initial HTTP connection) for an attacker to downgrade or redirect the -# request. The following header ensures that browser will ONLY connect to your -# server via HTTPS, regardless of what the users type in the address bar. -# http://www.html5rocks.com/en/tutorials/security/transport-layer-security/ - -# -# Header set Strict-Transport-Security max-age=16070400; -# - -# ------------------------------------------------------------------------------ -# | Server software information | -# ------------------------------------------------------------------------------ - -# Avoid displaying the exact Apache version number, the description of the -# generic OS-type and the information about Apache's compiled-in modules. - -# ADD THIS DIRECTIVE IN THE `httpd.conf` AS IT WILL NOT WORK IN THE `.htaccess`! - -# ServerTokens Prod - - -# ############################################################################## -# # WEB PERFORMANCE # -# ############################################################################## - -# ------------------------------------------------------------------------------ -# | Compression | -# ------------------------------------------------------------------------------ - - - - # Force compression for mangled headers. - # http://developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping - - - SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding - RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding - - - - # Compress all output labeled with one of the following MIME-types - # (for Apache versions below 2.3.7, you don't need to enable `mod_filter` - # and can remove the `` and `` lines - # as `AddOutputFilterByType` is still in the core directives). - - AddOutputFilterByType DEFLATE application/atom+xml \ - application/javascript \ - application/json \ - application/rss+xml \ - application/vnd.ms-fontobject \ - application/x-font-ttf \ - application/x-web-app-manifest+json \ - application/xhtml+xml \ - application/xml \ - font/opentype \ - image/svg+xml \ - image/x-icon \ - text/css \ - text/html \ - text/plain \ - text/x-component \ - text/xml - - - - -# ------------------------------------------------------------------------------ -# | Content transformations | -# ------------------------------------------------------------------------------ - -# Prevent some of the mobile network providers from modifying the content of -# your site: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5. - -# -# Header set Cache-Control "no-transform" -# - -# ------------------------------------------------------------------------------ -# | ETag removal | -# ------------------------------------------------------------------------------ - -# Since we're sending far-future expires headers (see below), ETags can -# be removed: http://developer.yahoo.com/performance/rules.html#etags. - -# `FileETag None` is not enough for every server. - - Header unset ETag - - -FileETag None - -# ------------------------------------------------------------------------------ -# | Expires headers (for better cache control) | -# ------------------------------------------------------------------------------ - -# The following expires headers are set pretty far in the future. If you don't -# control versioning with filename-based cache busting, consider lowering the -# cache time for resources like CSS and JS to something like 1 week. - - - - ExpiresActive on - ExpiresDefault "access plus 1 month" - - # CSS - ExpiresByType text/css "access plus 1 year" - - # Data interchange - ExpiresByType application/json "access plus 0 seconds" - ExpiresByType application/xml "access plus 0 seconds" - ExpiresByType text/xml "access plus 0 seconds" - - # Favicon (cannot be renamed!) - ExpiresByType image/x-icon "access plus 1 week" - - # HTML components (HTCs) - ExpiresByType text/x-component "access plus 1 month" - - # HTML - ExpiresByType text/html "access plus 0 seconds" - - # JavaScript - ExpiresByType application/javascript "access plus 1 year" - - # Manifest files - ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds" - ExpiresByType text/cache-manifest "access plus 0 seconds" - - # Media - ExpiresByType audio/ogg "access plus 1 month" - ExpiresByType image/gif "access plus 1 month" - ExpiresByType image/jpeg "access plus 1 month" - ExpiresByType image/png "access plus 1 month" - ExpiresByType video/mp4 "access plus 1 month" - ExpiresByType video/ogg "access plus 1 month" - ExpiresByType video/webm "access plus 1 month" - - # Web feeds - ExpiresByType application/atom+xml "access plus 1 hour" - ExpiresByType application/rss+xml "access plus 1 hour" - - # Web fonts - ExpiresByType application/font-woff "access plus 1 month" - ExpiresByType application/vnd.ms-fontobject "access plus 1 month" - ExpiresByType application/x-font-ttf "access plus 1 month" - ExpiresByType font/opentype "access plus 1 month" - ExpiresByType image/svg+xml "access plus 1 month" - - - -# ------------------------------------------------------------------------------ -# | Filename-based cache busting | -# ------------------------------------------------------------------------------ - -# If you're not using a build process to manage your filename version revving, -# you might want to consider enabling the following directives to route all -# requests such as `/css/style.12345.css` to `/css/style.css`. - -# To understand why this is important and a better idea than `*.css?v231`, read: -# http://stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring - -# -# RewriteCond %{REQUEST_FILENAME} !-f -# RewriteCond %{REQUEST_FILENAME} !-d -# RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpg|gif)$ $1.$3 [L] -# - -# ------------------------------------------------------------------------------ -# | File concatenation | -# ------------------------------------------------------------------------------ - -# Allow concatenation from within specific CSS and JS files, e.g.: -# Inside of `script.combined.js` you could have -# -# -# and they would be included into this single file. - -# -# -# Options +Includes -# AddOutputFilterByType INCLUDES application/javascript application/json -# SetOutputFilter INCLUDES -# -# -# Options +Includes -# AddOutputFilterByType INCLUDES text/css -# SetOutputFilter INCLUDES -# -# - -# ------------------------------------------------------------------------------ -# | Persistent connections | -# ------------------------------------------------------------------------------ - -# Allow multiple requests to be sent over the same TCP connection: -# http://httpd.apache.org/docs/current/en/mod/core.html#keepalive. - -# Enable if you serve a lot of static content but, be aware of the -# possible disadvantages! - -# -# Header set Connection Keep-Alive -# diff --git a/__html/app/favicon.ico b/__html/app/favicon.ico deleted file mode 100644 index 372714a41ac4953a6d652ce2a4093565bb013a6e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6782 zcmeH~OKc5M7{^bw+)5+$el(95G2*O6%oRMSfLS%Cenq44Pqf}6BcwqB7%g7 zorQ&0LPO-H6+%zNBOV*cMGz%Y;vIVZ{^!mxxt;6Y#no8MX@2*c`Q|&{`R0GlnVA|> z#9wu_;kU{(R~R$i7{jS!4OV{FCZ$dE8z~Se5GfET5GfET5T-y6&Tg<1VK(qeO?kes z_gMwBHn(SB2TVy{SIxoZ;)=P>=YX9_OsO%q2#`P6 zl)FcD#o-9d8yFLe*YR(Sb`pCDy+)?{sD|5Mcfn=w{OXh0Tzx}{X@L$n4Xc4bp)u?* zQ2mOz4*Q`7GLwazyFAkA3ba8i-Otr@ljBa91!d^M{b%Z@b5{ep*%@#j4&fVuodet9 zEF|GP%paJ?)u8_Mz~`7<4q8)VL36_xb`d;+ zfb}2^UjmEP)!d974PLC@SJwHY5jX1MzhZmg4xEI|Pz!6}BD{syAT6GP#t=W?1eAmF zN+XS_xmyfZLG?AlIZ&TdQ1xdmsh-THId}rL3Hrbv&$mDEy#mdH_QGL!2mbY-{f=LA zwgQfV?pZp01mzJLL-(S7TY#~(2L9IE{gx2B4jw{q%;2%|CLvpWiv0|qAlNV4@de^M zy;Y;zcjzw7w9kW0KBmCf>97x;K|f^6T?oJQJ^V`Un>29Xl+XwZwFflL4d?)Ak_27Pbsqb28=myCNC)nRjW9K`ExZI@6}ElAI@|Es=1lp-1`QXoJul$5YRhw>}=@1J9%;x5SENODkJr*w)taM5U}LF)i2xs1DgCNCF>< jhJVJL<-^~&{t3@=L3yaV&$B5$hTVPm_MhBWhF-q_M7z&N diff --git a/__html/app/images/logo.svg b/__html/app/images/logo.svg deleted file mode 100644 index 31e11ac..0000000 --- a/__html/app/images/logo.svg +++ /dev/null @@ -1,50 +0,0 @@ - - - -image/svg+xml \ No newline at end of file diff --git a/__html/app/index.html b/__html/app/index.html deleted file mode 100644 index 6aa9128..0000000 --- a/__html/app/index.html +++ /dev/null @@ -1,118 +0,0 @@ - - - - - hyperfox live - - - - - - - - - - - - - - - - - - -
- - - -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/__html/app/scripts/app.js b/__html/app/scripts/app.js deleted file mode 100644 index 8e7acad..0000000 --- a/__html/app/scripts/app.js +++ /dev/null @@ -1,49 +0,0 @@ -'use strict'; - -/** - * @ngdoc overview - * @name webApp - * @description - * # webApp - * - * Main module of the application. - */ -angular - .module('webApp', [ - 'ngAnimate', - 'ngCookies', - 'ngResource', - 'ngRoute', - 'ngSanitize', - 'ngTouch' - //'luegg.directives' - ]) - .config(function ($routeProvider) { - $routeProvider - .when('/details/:id', { - templateUrl: 'views/details.html', - controller: 'DetailsCtrl' - }) - .when('/:page?', { - templateUrl: 'views/main.html', - controller: 'MainCtrl' - }) - .otherwise({ - redirectTo: '/#/' - }); - }) - .directive('tooltip', function(){ - return { - restrict: 'A', - link: function(scope, element, attrs) { - $(element).hover(function(){ - // on mouseenter - $(element).tooltip('show'); - }, function(){ - // on mouseleave - $(element).tooltip('hide'); - }); - } - }; - }); - ; diff --git a/__html/app/scripts/controllers/main.js b/__html/app/scripts/controllers/main.js deleted file mode 100644 index 85f3d96..0000000 --- a/__html/app/scripts/controllers/main.js +++ /dev/null @@ -1,142 +0,0 @@ -'use strict'; - -var ERR_HYPERFOX_NOT_RUNNING = 'Could not connect to the Hyperfox API. Seems like hyperfox is not running on your local box.'; - -/** - * @ngdoc function - * @name webApp.controller:MainCtrl - * @description - * # MainCtrl - * Controller of the webApp - */ -angular.module('webApp') - .controller('ParentCtrl', function($scope, $routeParams, api) { - - $scope.apierror = null; - - $scope.setTerms = function() { - $scope.$broadcast('search'); - }; - - }) - .controller('DetailsCtrl', function($scope, $routeParams, api) { - $scope.currentID = parseInt($routeParams.id, 10); - $scope.details = {}; - - api.get($scope.currentID).then(function(res) { - $scope.apierror = null; - - $scope.details = res; - }, function(reason) { - $scope.apierror = ERR_HYPERFOX_NOT_RUNNING; - }); - - $scope.$on('search', function() { - location.href = '/#/1'; - refresh(); - }); - - }) - .controller('MainCtrl', function($scope, $routeParams, api) { - - if ($routeParams.source) { - window.localStorage.setItem('source', $routeParams.source); - }; - - $scope.$on('search', function() { - location.href = '/#/'; - refresh(); - }); - - $scope.requests = []; - $scope.totalPages = 0; - $scope.currentPage = parseInt($routeParams.page || 1, 10); - - var pull = function(page, q) { - api.pull(page, q).then(function(res) { - $scope.apierror = null; - - $scope.requests = res.data; - $scope.totalPages = res.pages; - $scope.currentPage = res.page; - - }, function(reason) { - $scope.apierror = ERR_HYPERFOX_NOT_RUNNING; - }); - }; - - var refresh = function() { - pull($scope.currentPage, $scope.q); - }; - - setInterval( - function() { - refresh(); - }, - 10000 - ); - - refresh(); - }) - .filter('mime', function() { - return function(input) { - var c = input.indexOf(';'); - if (c >= 0) { - return input.substr(0, c); - }; - return input; - } - }) - .filter('origin', function() { - return function(input) { - if (input) { - var c = input.indexOf(':'); - if (c >= 0) { - return input.substr(0, c); - }; - } - return input; - } - }) - .filter('size', function() { - return function(input) { - if (!input) { - return '-'; - }; - var kb = 1024; - if (input < kb) { - return input + 'b'; - } else if (input < kb*kb) { - return (input/kb).toFixed(2) + 'Kb'; - } - return (input/(kb*kb)).toFixed(2) + 'Mb'; - } - }) - .filter('time', function() { - return function(input) { - if (input < 1e9) { - return (input/1e6).toFixed(2) + 'ms'; - }; - return (input/1e9).toFixed(2) + 's'; - } - }) - .filter('api_request', function() { - return function(input) { - return endpoint(input); - } - }) - .filter('pageRange', function() { - return function(input, current, total, size) { - var sz = 3; - - var lo = Math.max(1, current - sz); - var hi = Math.min(total, current + sz); - - var i; - for (i = lo; i <= hi; i++) { - input.push(i); - }; - - return input; - }; - }); diff --git a/__html/app/scripts/services/main.js b/__html/app/scripts/services/main.js deleted file mode 100644 index 8f2b071..0000000 --- a/__html/app/scripts/services/main.js +++ /dev/null @@ -1,62 +0,0 @@ -'use strict'; - -function endpoint(url) { - var prefix = window.localStorage.getItem('source'); - - if (!prefix) { - prefix = '127.0.0.1:3030'; - }; - - return 'http://' + prefix + url; -} - -var downloadLink = function(id) { - return endpoint('/download?id='+id); -}; - -angular.module('webApp') - .service('api', function($http) { - var api = {}; - - api.get = function(id) { - var req = { - 'method': 'POST', - 'url': endpoint('/get'), - 'data': $.param({ - 'id': id - }), - 'headers': { - 'Content-Type': 'application/x-www-form-urlencoded' - } - }; - - var promise = $http(req).then(function(res) { - return res.data; - }); - - return promise; - }; - - api.pull = function(page, q) { - - var req = { - 'method': 'POST', - 'url': endpoint('/pull'), - 'data': $.param({ - 'page': page, - 'q': q || '' - }), - 'headers': { - 'Content-Type': 'application/x-www-form-urlencoded' - } - }; - - var promise = $http(req).then(function(res) { - return res.data; - }); - - return promise; - }; - - return api; - }); diff --git a/__html/app/styles/main.scss b/__html/app/styles/main.scss deleted file mode 100644 index 34c40ff..0000000 --- a/__html/app/styles/main.scss +++ /dev/null @@ -1,197 +0,0 @@ -$icon-font-path: "../bower_components/bootstrap-sass-official/assets/fonts/bootstrap/"; -// bower:scss -@import "bootstrap-sass-official/assets/stylesheets/_bootstrap.scss"; -// endbower - -.browsehappy { - margin: 0.2em 0; - background: #ccc; - color: #000; - padding: 0.2em 0; -} - -/* Space out content a bit */ -body { - padding-top: 70px; - padding-bottom: 20px; -} - -/* Everything but the jumbotron gets side spacing for mobile first views */ -.header, -.marketing, -.footer { - padding-left: 15px; - padding-right: 15px; -} - -/* Custom page header */ -.header { - border-bottom: 1px solid #e5e5e5; - - /* Make the masthead heading the same height as the navigation */ - h3 { - margin-top: 0; - margin-bottom: 0; - line-height: 40px; - padding-bottom: 19px; - } -} - -/* Custom page footer */ -.footer { - padding-top: 19px; - color: #777; - border-top: 1px solid #e5e5e5; -} - -.container-narrow > hr { - margin: 30px 0; -} - -/* Main marketing message and sign up button */ -.jumbotron { - text-align: center; - border-bottom: 1px solid #e5e5e5; - - .btn { - font-size: 21px; - padding: 14px 24px; - } -} - -/* Supporting marketing content */ -.marketing { - margin: 40px 0; - - p + h4 { - margin-top: 28px; - } -} - -/* Responsive: Portrait tablets and up */ -@media screen and (min-width: 768px) { - .container { - max-width: 730px; - } - - /* Remove the padding we set earlier */ - .header, - .marketing, - .footer { - padding-left: 0; - padding-right: 0; - } - /* Space out the masthead */ - .header { - margin-bottom: 30px; - } - /* Remove the bottom border on the jumbotron for visual effect */ - .jumbotron { - border-bottom: 0; - } -} -#requests-paginator { - margin-left: 10px; - margin-right: 10px; - position: fixed; - bottom: 10px; -} -#requests-paginator ul { - margin: 0px; - padding: 0px; -} -#details-wrapper { - height: auto; -} -#details-wrapper dd { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} -.container { - max-width: 100%; -} -.data-rows { - height: auto; - overflow-y: scroll; - position: fixed; - top: 50px; - left: 0px; - right: 0px; - bottom: 65px; -} -.content-fixed { - position: fixed; - top: 0px; - left: 0px; - bottom: 0px; - right: 0px; -} -.content-fluid { - width: 100%; -} -#requests-wrapper th { - text-align: center; -} - -#requests-wrapper th.th-scheme { - width: 80px; -} -#requests-wrapper th.th-path { - width: 300px; -} -#requests-wrapper th.th-type { - width: 120px; -} -#requests-wrapper th.th-direction { - width: 100px; -} -#requests-wrapper th.th-host { - width: 200px; -} -#requests-wrapper th.th-method { - width: 80px; -} -#requests-wrapper th.th-origin { - width: 120px; -} -#requests-wrapper tbody td { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -#requests-wrapper td.td-path { - max-width: 300px; -} -#requests-wrapper td.td-host { - max-width: 200px; -} -#requests-wrapper td.td-scheme { - text-align: center; -} -#requests-wrapper td.td-type { - max-width: 120px; - text-align: center; -} -#requests-wrapper td.td-origin { - max-width: 150px; -} -#requests-wrapper td.td-method { - text-align: center; -} -#requests-wrapper td.td-status { - text-align: center; -} -#requests-wrapper td.td-size { - text-align: center; -} -#requests-wrapper td.td-actions { - text-align: center; -} -.navbar-brand img { - display: inline; -} -.buttons { - text-align: right; -} diff --git a/__html/app/views/details.html b/__html/app/views/details.html deleted file mode 100644 index 213b50f..0000000 --- a/__html/app/views/details.html +++ /dev/null @@ -1,70 +0,0 @@ -
-
- - - -
- -

{{details.origin | origin}} -> {{details.host}}

- -

Abstract

- -

- On {{details.date_start | date: 'MMM d, y H:mm:ss'}} a - {{details.method}} request was issued to {{details.host}} by - {{details.origin | origin}}. -

-

- The request had a size of {{details.content_length | size}} and took - {{details.time_taken | time}} to complete. -

-

- The request took {{details.time_taken | time}} to complete. -

- -

-
- -
- -
-
-
- - -
-
- -

- - Server response -

- -
- - -
{{header}}
-
{{value}}
-
-
-
- -

- - Client request -

- -
- - -
{{header}}
-
{{value}}
-
-
-
-
- -
-
diff --git a/__html/app/views/main.html b/__html/app/views/main.html deleted file mode 100644 index 1e2b241..0000000 --- a/__html/app/views/main.html +++ /dev/null @@ -1,108 +0,0 @@ - - - -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- -
- - - -
-
diff --git a/__html/bower.json b/__html/bower.json deleted file mode 100644 index f33a5b7..0000000 --- a/__html/bower.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "web", - "version": "0.0.0", - "dependencies": { - "angular": "^1.3.0", - "json3": "^3.3.0", - "es5-shim": "^4.0.0", - "bootstrap-sass-official": "^3.2.0", - "angular-animate": "^1.3.0", - "angular-cookies": "^1.3.0", - "angular-resource": "^1.3.0", - "angular-route": "^1.3.0", - "angular-sanitize": "^1.3.0", - "angular-touch": "^1.3.0", - "angularjs-scroll-glue-Luegg": "~2.0.3" - }, - "devDependencies": { - "angular-mocks": "~1.3.0", - "angular-scenario": "~1.3.0" - }, - "appPath": "app" -} diff --git a/__html/package.json b/__html/package.json deleted file mode 100644 index 03d9e6b..0000000 --- a/__html/package.json +++ /dev/null @@ -1,44 +0,0 @@ -{ - "name": "web", - "version": "0.0.0", - "dependencies": { - "grunt": "~0.4.5" - }, - "devDependencies": { - "grunt": "^0.4.1", - "grunt-autoprefixer": "^0.7.3", - "grunt-concurrent": "^0.5.0", - "grunt-contrib-clean": "^0.5.0", - "grunt-contrib-compass": "~1.0.1", - "grunt-contrib-concat": "^0.4.0", - "grunt-contrib-connect": "^0.7.1", - "grunt-contrib-copy": "^0.5.0", - "grunt-contrib-cssmin": "^0.9.0", - "grunt-contrib-htmlmin": "^0.3.0", - "grunt-contrib-imagemin": "^0.8.1", - "grunt-contrib-jshint": "^0.10.0", - "grunt-contrib-uglify": "^0.4.0", - "grunt-contrib-watch": "^0.6.1", - "grunt-filerev": "^0.2.1", - "grunt-google-cdn": "^0.4.0", - "grunt-karma": "^0.9.0", - "grunt-newer": "^0.7.0", - "grunt-ng-annotate": "^0.4.0", - "grunt-svgmin": "^0.4.0", - "grunt-usemin": "^2.1.1", - "grunt-wiredep": "^1.7.0", - "jasmine-core": "^2.1.3", - "jshint-stylish": "^0.2.0", - "karma": "^0.12.28", - "karma-jasmine": "^0.3.2", - "karma-phantomjs-launcher": "^0.1.4", - "load-grunt-tasks": "^0.4.0", - "time-grunt": "^0.3.1" - }, - "engines": { - "node": ">=0.10.0" - }, - "scripts": { - "test": "grunt test" - } -} diff --git a/__html/test/.jshintrc b/__html/test/.jshintrc deleted file mode 100644 index b1be025..0000000 --- a/__html/test/.jshintrc +++ /dev/null @@ -1,36 +0,0 @@ -{ - "node": true, - "browser": true, - "esnext": true, - "bitwise": true, - "camelcase": true, - "curly": true, - "eqeqeq": true, - "immed": true, - "indent": 2, - "latedef": true, - "newcap": true, - "noarg": true, - "quotmark": "single", - "regexp": true, - "undef": true, - "unused": true, - "strict": true, - "trailing": true, - "smarttabs": true, - "globals": { - "after": false, - "afterEach": false, - "angular": false, - "before": false, - "beforeEach": false, - "browser": false, - "describe": false, - "expect": false, - "inject": false, - "it": false, - "jasmine": false, - "spyOn": false - } -} - diff --git a/__html/test/karma.conf.js b/__html/test/karma.conf.js deleted file mode 100644 index 5242282..0000000 --- a/__html/test/karma.conf.js +++ /dev/null @@ -1,75 +0,0 @@ -// Karma configuration -// http://karma-runner.github.io/0.12/config/configuration-file.html -// Generated on 2014-12-20 using -// generator-karma 0.8.3 - -module.exports = function(config) { - 'use strict'; - - config.set({ - // enable / disable watching file and executing tests whenever any file changes - autoWatch: true, - - // base path, that will be used to resolve files and exclude - basePath: '../', - - // testing framework to use (jasmine/mocha/qunit/...) - frameworks: ['jasmine'], - - // list of files / patterns to load in the browser - files: [ - 'bower_components/angular/angular.js', - 'bower_components/angular-mocks/angular-mocks.js', - 'bower_components/angular-animate/angular-animate.js', - 'bower_components/angular-cookies/angular-cookies.js', - 'bower_components/angular-resource/angular-resource.js', - 'bower_components/angular-route/angular-route.js', - 'bower_components/angular-sanitize/angular-sanitize.js', - 'bower_components/angular-touch/angular-touch.js', - 'app/scripts/**/*.js', - 'test/mock/**/*.js', - 'test/spec/**/*.js' - ], - - // list of files / patterns to exclude - exclude: [], - - // web server port - port: 8080, - - // Start these browsers, currently available: - // - Chrome - // - ChromeCanary - // - Firefox - // - Opera - // - Safari (only Mac) - // - PhantomJS - // - IE (only Windows) - browsers: [ - 'PhantomJS' - ], - - // Which plugins to enable - plugins: [ - 'karma-phantomjs-launcher', - 'karma-jasmine' - ], - - // Continuous Integration mode - // if true, it capture browsers, run tests and exit - singleRun: false, - - colors: true, - - // level of logging - // possible values: LOG_DISABLE || LOG_ERROR || LOG_WARN || LOG_INFO || LOG_DEBUG - logLevel: config.LOG_INFO, - - // Uncomment the following lines if you are using grunt's server to run the tests - // proxies: { - // '/': 'http://localhost:9000/' - // }, - // URL root prevent conflicts with the site root - // urlRoot: '_karma_' - }); -}; diff --git a/__html/test/spec/controllers/about.js b/__html/test/spec/controllers/about.js deleted file mode 100644 index 2366696..0000000 --- a/__html/test/spec/controllers/about.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -describe('Controller: AboutCtrl', function () { - - // load the controller's module - beforeEach(module('webApp')); - - var AboutCtrl, - scope; - - // Initialize the controller and a mock scope - beforeEach(inject(function ($controller, $rootScope) { - scope = $rootScope.$new(); - AboutCtrl = $controller('AboutCtrl', { - $scope: scope - }); - })); - - it('should attach a list of awesomeThings to the scope', function () { - expect(scope.awesomeThings.length).toBe(3); - }); -}); diff --git a/__html/test/spec/controllers/main.js b/__html/test/spec/controllers/main.js deleted file mode 100644 index 482025b..0000000 --- a/__html/test/spec/controllers/main.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict'; - -describe('Controller: MainCtrl', function () { - - // load the controller's module - beforeEach(module('webApp')); - - var MainCtrl, - scope; - - // Initialize the controller and a mock scope - beforeEach(inject(function ($controller, $rootScope) { - scope = $rootScope.$new(); - MainCtrl = $controller('MainCtrl', { - $scope: scope - }); - })); - - it('should attach a list of awesomeThings to the scope', function () { - expect(scope.awesomeThings.length).toBe(3); - }); -}); diff --git a/app/components/NavigationBar/tests/index.test.js b/app/components/NavigationBar/tests/index.test.js index 8c20525..629b0a6 100755 --- a/app/components/NavigationBar/tests/index.test.js +++ b/app/components/NavigationBar/tests/index.test.js @@ -11,7 +11,7 @@ import React from 'react' describe('', () => { it('should render the Logo', () => { - const navLogo = () + const navLogo = () const renderedComponent = shallow( ) diff --git a/app/components/Pagination/tests/index.test.js b/app/components/Pagination/tests/index.test.js index 8c20525..4223173 100644 --- a/app/components/Pagination/tests/index.test.js +++ b/app/components/Pagination/tests/index.test.js @@ -1,20 +1,11 @@ -/* Testing our NavigationBar component */ +/* Testing our Pagination component */ -import NavigationBar from '../index' - -import Logo from 'components/Icons/Logo' -import styles from '../styles.css' +import Pagination from '../index' import expect from 'expect' import { shallow } from 'enzyme' import React from 'react' -describe('', () => { - it('should render the Logo', () => { - const navLogo = () - const renderedComponent = shallow( - - ) - expect(renderedComponent.contains(navLogo)).toEqual(true) - }) +describe('', () => { + }) diff --git a/electron/main.js b/electron/main.js new file mode 100644 index 0000000..27948cf --- /dev/null +++ b/electron/main.js @@ -0,0 +1,32 @@ +const electron = require('electron') + +const app = electron.app +const BrowserWindow = electron.BrowserWindow + +let mainWindow +function createWindow () { + mainWindow = new BrowserWindow({ + width: 800, + height: 600, + titleBarStyle: 'hidden', + title: 'Hyperfox' + }) + mainWindow.loadURL(`http://lolcathost:3000`) + mainWindow.webContents.openDevTools() + mainWindow.on('closed', function () { + mainWindow = null + }) +} + +app.on('ready', createWindow) +app.on('window-all-closed', function () { + if (process.platform !== 'darwin') { + app.quit() + } +}) + +app.on('activate', function () { + if (mainWindow === null) { + createWindow() + } +}) diff --git a/internals/scripts/getTranslations.js b/internals/scripts/getTranslations.js index 7d3e8f6..c166303 100644 --- a/internals/scripts/getTranslations.js +++ b/internals/scripts/getTranslations.js @@ -2,147 +2,129 @@ * This script will extract the internationalization messages from all components and package them in the transalation json files in the translations file. */ -const fs = require('fs'); -const nodeGlob = require('glob'); -const chalk = require('chalk'); -const transform = require('babel-core').transform; -const pkg = require('../../package.json'); -const i18n = require('../../app/i18n'); +const fs = require('fs') +const nodeGlob = require('glob') +const chalk = require('chalk') +const transform = require('babel-core').transform +const pkg = require('../../package.json') +const i18n = require('../../app/i18n') -require('shelljs/global'); +require('shelljs/global') // Glob to match all js files except test files -const FILES_TO_PARSE = 'app/**/!(*.test).js'; -const locales = i18n.appLocales; +const FILES_TO_PARSE = 'app/**/!(*.test).js' +const locales = i18n.appLocales // Wrap async functions below into a promise const glob = (pattern) => new Promise((resolve, reject) => { - nodeGlob(pattern, (error, value) => (error ? reject(error) : resolve(value))); -}); + nodeGlob(pattern, (error, value) => (error ? reject(error) : resolve(value))) +}) const readFile = (fileName) => new Promise((resolve, reject) => { - fs.readFile(fileName, (error, value) => (error ? reject(error) : resolve(value))); -}); + fs.readFile(fileName, (error, value) => (error ? reject(error) : resolve(value))) +}) const writeFile = (fileName, data) => new Promise((resolve, reject) => { - fs.writeFile(fileName, data, (error, value) => (error ? reject(error) : resolve(value))); -}); + fs.writeFile(fileName, data, (error, value) => (error ? reject(error) : resolve(value))) +}) // Helper function to log a gray dividing line const logDivider = () => { - console.log( - chalk.gray('------------------------------------------------------------------------') - ); -}; + console.log(chalk.gray('------------------------------------------------------------------------')) +} // Helper function to log an error in bold red const logError = (error, ...args) => { - console.error( - chalk.bold.red(error), - ...args - ); -}; + console.error(chalk.bold.red(error), ...args) +} // Helper function to log a success message in bold green const logSuccess = (success, ...args) => { - console.log( - chalk.green(success), - ...args - ); -}; + console.log(chalk.green(success), ...args) +} // Store existing translations into memory -const oldLocaleMappings = []; -const localeMappings = []; +const oldLocaleMappings = [] +const localeMappings = [] // Loop to run once per locale for (const locale of locales) { - oldLocaleMappings[locale] = {}; - localeMappings[locale] = {}; + oldLocaleMappings[locale] = {} + localeMappings[locale] = {} // File to store translation messages into - const translationFileName = `app/translations/${locale}.json`; + const translationFileName = `app/translations/${locale}.json` try { // Parse the old translation message JSON files - const messages = JSON.parse(fs.readFileSync(translationFileName)); + const messages = JSON.parse(fs.readFileSync(translationFileName)) for (const message of messages) { - oldLocaleMappings[locale][message.id] = message; + oldLocaleMappings[locale][message.id] = message } } catch (error) { if (error.code !== 'ENOENT') { - logError(`There was an error loading this translation file: ${translationFileName}\n${error}`); + logError(`There was an error loading this translation file: ${translationFileName}\n${error}`) } } } - const extractFromFile = async (fileName) => { try { - const code = await readFile(fileName); + const code = await readFile(fileName) // Use babel plugin to extract instances where react-intl is used const { metadata: result } = await transform(code, { presets: pkg.babel.presets, - plugins: [ - ['react-intl'], - ], - }); + plugins: [['react-intl']] + }) for (const message of result['react-intl'].messages) { for (const locale of locales) { - const oldLocaleMapping = oldLocaleMappings[locale][message.id]; + const oldLocaleMapping = oldLocaleMappings[locale][message.id] // Merge old translations into the babel extracted instances where react-intl is used localeMappings[locale][message.id] = { id: message.id, description: message.description, defaultMessage: message.defaultMessage, - message: (oldLocaleMapping && oldLocaleMapping.message) ? oldLocaleMapping.message : '', - }; + message: (oldLocaleMapping && oldLocaleMapping.message) ? oldLocaleMapping.message : '' + } } } } catch (error) { - logError(`There was an error transforming this file: ${fileName}\n${error}`); + logError(`There was an error transforming this file: ${fileName}\n${error}`) } }; -(async function main() { - const files = await glob(FILES_TO_PARSE); +(async function main () { + const files = await glob(FILES_TO_PARSE) // Run extraction on all files that match the glob on line 16 await Promise.all( files.map((fileName) => extractFromFile(fileName)) - ); + ) // Make the directory if it doesn't exist, especially for first run - mkdir('-p', 'app/translations'); - logDivider(); + mkdir('-p', 'app/translations') + logDivider() for (const locale of locales) { - const translationFileName = `app/translations/${locale}.json`; + const translationFileName = `app/translations/${locale}.json` try { // Sort the translation JSON file so that git diffing is easier // Otherwise the translation messages will jump around every time we extract let messages = Object.values(localeMappings[locale]).sort((a, b) => { - a = a.id.toUpperCase(); - b = b.id.toUpperCase(); + a = a.id.toUpperCase() + b = b.id.toUpperCase() if (a < b) { - return -1; + return -1 } else if (a > b) { - return 1; + return 1 } else { - return 0; + return 0 } - }); + }) // Write to file the JSON representation of the translation messages - await writeFile( - translationFileName, - JSON.stringify( - messages, - null, - 2 - ) - ); + await writeFile(translationFileName, JSON.stringify(messages, null, 2)) - logSuccess(`Translation file for ${locale} successfully saved to: ${translationFileName}`); + logSuccess(`Translation file for ${locale} successfully saved to: ${translationFileName}`) } catch (error) { - logError(`There was an error saving this translation file: ${translationFileName}\n${error}`); + logError(`There was an error saving this translation file: ${translationFileName}\n${error}`) } } - logDivider(); -}()); + logDivider() +}()) diff --git a/package.json b/package.json index 5304a4b..69eea39 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "build:clean": "rimraf ./build/*", "build:dll": "node ./internals/scripts/dependencies.js", "start": "cross-env NODE_ENV=development node server", + "start:electron": "electron ./electron/main.js", "start:production": "npm run build && npm run start:prod", "start:prod": "cross-env NODE_ENV=production node server", "test": "cross-env NODE_ENV=test karma start internals/testing/karma.conf.js --single-run", @@ -28,7 +29,12 @@ }, "babel": { "presets": [ - "es2015-webpack", + [ + "es2015", + { + "modules": false + } + ], "react", "stage-0" ], @@ -63,94 +69,91 @@ ] }, "dependencies": { - "babel-polyfill": "^6.7.4", + "babel-polyfill": "6.13.0", "bulma": "0.0.28", "chalk": "^1.1.3", "classnames": "^2.2.5", "compression": "^1.6.1", - "express": "^4.13.4", - "fontfaceobserver": "^1.7.1", + "express": "4.14.0", + "fontfaceobserver": "2.0.4", "history": "^2.1.0", "immutable": "^3.8.1", "intl": "^1.2.4", "minimist": "^1.2.0", - "react": "^15.0.1", - "react-dom": "^15.0.1", - "react-intl": "^2.1.3", + "react": "15.3.1", + "react-dom": "15.3.1", + "react-intl": "^2.1.5", "react-redux": "^4.4.5", - "react-router": "^2.3.0", - "react-router-redux": "^4.0.4", - "react-router-scroll": "^0.2.0", - "redux": "^3.5.2", - "redux-immutable": "^3.0.6", - "redux-saga": "^0.10.0", - "reselect": "^2.5.1", - "sanitize.css": "^3.3.0", + "react-router": "^2.8.0", + "react-router-redux": "^4.0.5", + "react-router-scroll": "^0.3.2", + "redux": "3.6.0", + "redux-immutable": "^3.0.8", + "redux-saga": "^0.11.1", + "reselect": "^2.5.3", + "sanitize.css": "^4.1.0", "whatwg-fetch": "^1.0.0" }, "devDependencies": { - "babel-cli": "^6.10.1", - "babel-core": "^6.7.7", - "babel-eslint": "^6.0.5", - "babel-loader": "^6.2.4", - "babel-plugin-react-intl": "^2.1.3", - "babel-plugin-react-transform": "^2.0.2", - "babel-plugin-transform-react-constant-elements": "^6.8.0", - "babel-plugin-transform-react-inline-elements": "^6.8.0", - "babel-plugin-transform-react-remove-prop-types": "^0.2.7", - "babel-preset-es2015": "^6.6.0", - "babel-preset-es2015-webpack": "^6.4.1", - "babel-preset-react": "^6.5.0", + "babel-cli": "6.14.0", + "babel-core": "6.14.0", + "babel-eslint": "6.1.2", + "babel-loader": "6.2.5", + "babel-plugin-react-intl": "2.2.0", + "babel-plugin-react-transform": "2.0.2", + "babel-plugin-transform-react-constant-elements": "6.9.1", + "babel-plugin-transform-react-inline-elements": "6.8.0", + "babel-plugin-transform-react-remove-prop-types": "0.2.9", + "babel-preset-es2015": "6.14.0", + "babel-preset-react": "6.11.1", "babel-preset-react-hmre": "^1.1.1", "babel-preset-stage-0": "^6.5.0", - "chai": "^3.5.0", - "chai-enzyme": "^0.4.2", - "cheerio": "^0.20.0", - "coveralls": "^2.11.9", - "cross-env": "^1.0.7", - "css-loader": "^0.23.1", - "enzyme": "^2.2.0", + "chai": "3.5.0", + "chai-enzyme": "0.5.1", + "cheerio": "^0.22.0", + "coveralls": "^2.11.12", + "cross-env": "2.0.1", + "css-loader": "0.25.0", + "electron-prebuilt": "^1.2.5", + "enzyme": "^2.4.1", "eventsource-polyfill": "^0.9.6", - "expect": "^1.18.0", - "expect-jsx": "^2.5.1", + "expect": "1.20.2", + "expect-jsx": "2.6.0", "exports-loader": "^0.6.3", - "extract-text-webpack-plugin": "^1.0.1", - "file-loader": "^0.8.5", + "extract-text-webpack-plugin": "2.0.0-beta.4", + "file-loader": "0.9.0", "html-loader": "^0.4.3", - "html-webpack-plugin": "^2.16.0", - "image-webpack-loader": "^1.8.0", + "html-webpack-plugin": "2.22.0", + "image-webpack-loader": "2.0.0", "imports-loader": "^0.6.5", - "isparta": "^4.0.0", - "isparta-loader": "^2.0.0", - "json-loader": "^0.5.4", - "karma": "^0.13.22", - "karma-chrome-launcher": "^1.0.1", - "karma-coverage": "^1.0.0", - "karma-firefox-launcher": "^1.0.0", - "karma-ie-launcher": "^1.0.0", - "karma-mocha": "^1.0.1", - "karma-mocha-reporter": "^2.0.3", - "karma-safari-launcher": "^1.0.0", - "karma-sourcemap-loader": "^0.3.7", - "karma-webpack": "^1.7.0", + "json-loader": "0.5.4", + "karma": "1.3.0", + "karma-chrome-launcher": "2.0.0", + "karma-coverage": "1.1.1", + "karma-firefox-launcher": "1.0.0", + "karma-ie-launcher": "1.0.0", + "karma-mocha": "1.1.1", + "karma-mocha-reporter": "2.1.0", + "karma-safari-launcher": "1.0.0", + "karma-sourcemap-loader": "0.3.7", + "karma-webpack": "1.8.0", "lodash": "^4.13.1", - "minimist": "^1.2.0", - "mocha": "^2.4.5", + "mocha": "3.0.2", "null-loader": "^0.1.1", - "offline-plugin": "^3.2.0", - "postcss-cssnext": "^2.5.2", - "postcss-focus": "^1.0.0", - "postcss-loader": "^0.9.1", - "postcss-reporter": "^1.3.3", + "offline-plugin": "3.4.2", + "postcss-cssnext": "2.8.0", + "postcss-focus": "1.0.0", + "postcss-loader": "0.13.0", + "postcss-reporter": "1.4.1", "precss": "^1.4.0", - "rimraf": "^2.5.2", - "shelljs": "^0.7.0", + "rimraf": "^2.5.4", + "shelljs": "^0.7.4", "sinon": "^2.0.0-pre", "style-loader": "^0.13.1", "url-loader": "^0.5.7", - "webpack": "2.1.0-beta.13", - "webpack-dev-middleware": "^1.6.1", - "webpack-hot-middleware": "^2.10.0" + "webpack": "2.1.0-beta.22", + "webpack-dev-middleware": "1.7.0", + "webpack-hot-middleware": "2.12.2" }, "standard": { "parser": "babel-eslint", From fc2563ccd272c0f6ce51b62b2f3dd9171e632fb8 Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Sun, 26 Jun 2016 22:32:00 -0500 Subject: [PATCH 24/34] Fix React Router Scroll bug --- app/app.js | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/app/app.js b/app/app.js index 5e89209..9096668 100755 --- a/app/app.js +++ b/app/app.js @@ -14,7 +14,8 @@ import ReactDOM from 'react-dom' import { Provider } from 'react-redux' import { applyRouterMiddleware, Router, browserHistory } from 'react-router' import { syncHistoryWithStore } from 'react-router-redux' -import useScroll from 'react-router-scroll' +import FontFaceObserver from 'fontfaceobserver'; +import { useScroll } from 'react-router-scroll'; import configureStore from './store' // Import Language Provider @@ -26,6 +27,15 @@ import { translationMessages } from './i18n' // import 'sanitize.css/lib/sanitize.css' import 'bulma/css/bulma.css' +const openSansObserver = new FontFaceObserver('Open Sans', {}); + +// When Open Sans is loaded, add a font-family using Open Sans to the body +openSansObserver.load().then(() => { + document.body.classList.add(styles.fontLoaded); +}, () => { + document.body.classList.remove(styles.fontLoaded); +}) + // Create redux store with history // this uses the singleton browserHistory provided by react-router // Optionally, this could be changed to leverage a created history @@ -69,9 +79,19 @@ if (module.hot) { // Chunked polyfill for browsers without Intl support if (!window.Intl) { - System.import('intl').then(render) + (new Promise((resolve) => { + resolve(System.import('intl')); + })) + .then(() => Promise.all([ + System.import('intl/locale-data/jsonp/en.js'), + System.import('intl/locale-data/jsonp/de.js'), + ])) + .then(() => render(translationMessages)) + .catch((err) => { + throw err; + }); } else { - render() + render(translationMessages); } // Install ServiceWorker and AppCache in the end since // it's not most important operation and if main code fails, From b832754f64eaa03f3d39a8ac4cf38db31fe52891 Mon Sep 17 00:00:00 2001 From: Rogelio Alberto Date: Mon, 27 Jun 2016 22:32:00 -0500 Subject: [PATCH 25/34] Typo --- app/app.js | 1 + app/components/Pagination/index.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/app.js b/app/app.js index 9096668..622a82b 100755 --- a/app/app.js +++ b/app/app.js @@ -25,6 +25,7 @@ import { translationMessages } from './i18n' // Import the CSS reset, which HtmlWebpackPlugin transfers to the build folder // import 'sanitize.css/lib/sanitize.css' +import styles from 'containers/App/styles.css'; import 'bulma/css/bulma.css' const openSansObserver = new FontFaceObserver('Open Sans', {}); diff --git a/app/components/Pagination/index.js b/app/components/Pagination/index.js index 6fdc223..5b2ce67 100644 --- a/app/components/Pagination/index.js +++ b/app/components/Pagination/index.js @@ -7,7 +7,7 @@ export default function Pagination () {