From 8db2dcb58be92944e69bd2178311b25466f8e2f7 Mon Sep 17 00:00:00 2001 From: kruczkowska Date: Tue, 28 Mar 2017 17:24:51 +0200 Subject: [PATCH] test app --- .editorconfig | 7 + .gitignore | 152 ++++++++ Dockerfile | 11 + LICENSE.txt | 21 + README.md | 38 +- package.json | 214 +++++++++++ src/actions/README.md | 3 + src/actions/runtime.js | 13 + src/client.js | 185 +++++++++ src/components/App.js | 68 ++++ src/components/Author/Author.css | 7 + src/components/Author/Author.js | 13 + src/components/Author/package.json | 6 + src/components/Commits/Commits.css | 3 + src/components/Commits/Commits.js | 14 + src/components/Commits/package.json | 6 + src/components/Header/Header.css | 7 + src/components/Header/Header.js | 10 + src/components/Header/package.json | 6 + src/components/Html.js | 84 ++++ src/components/Layout/Layout.css | 170 ++++++++ src/components/Layout/Layout.js | 30 ++ src/components/Layout/Layout.test.js | 39 ++ src/components/Layout/package.json | 6 + src/components/Main/Main.css | 6 + src/components/Main/Main.js | 11 + src/components/Main/package.json | 6 + src/components/SingleCommit/SingleCommit.css | 0 src/components/SingleCommit/SingleCommit.js | 16 + .../SingleCommit/SingleCommit.test.js | 34 ++ src/components/SingleCommit/package.json | 6 + src/components/variables.css | 31 ++ src/config.js | 22 ++ src/constants/index.js | 3 + src/core/DOMUtils.js | 36 ++ src/core/devUtils.js | 22 ++ src/core/fetch/fetch.client.js | 15 + src/core/fetch/fetch.server.js | 33 ++ src/core/fetch/package.json | 6 + src/core/history.js | 14 + src/reducers/index.js | 6 + src/reducers/runtime.js | 13 + src/routes/author/Author.js | 35 ++ src/routes/author/index.js | 27 ++ src/routes/commits/Commits.js | 39 ++ src/routes/commits/index.js | 26 ++ src/routes/error/ErrorPage.css | 56 +++ src/routes/error/ErrorPage.js | 45 +++ src/routes/error/index.js | 26 ++ src/routes/home/Home.js | 16 + src/routes/home/Home.test.js | 21 + src/routes/home/index.js | 26 ++ src/routes/index.js | 38 ++ src/routes/notFound/NotFound.css | 21 + src/routes/notFound/NotFound.js | 31 ++ src/routes/notFound/index.js | 28 ++ src/server.js | 144 +++++++ src/store/configureStore.js | 42 ++ src/store/createHelpers.js | 32 ++ src/store/logger/logger.client.js | 7 + src/store/logger/logger.server.js | 13 + src/store/logger/package.json | 6 + test/.eslintrc | 9 + test/setup.js | 25 ++ tools/.eslintrc | 6 + tools/README.md | 50 +++ tools/build.js | 36 ++ tools/bundle.js | 29 ++ tools/clean.js | 31 ++ tools/copy.js | 64 +++ tools/deploy.js | 86 +++++ tools/lib/cp.js | 22 ++ tools/lib/fs.js | 79 ++++ tools/lib/markdown-loader.js | 23 ++ tools/postcss.config.js | 63 +++ tools/render.js | 62 +++ tools/run.js | 36 ++ tools/runServer.js | 71 ++++ tools/start.js | 90 +++++ tools/webpack.config.js | 363 ++++++++++++++++++ 80 files changed, 3201 insertions(+), 16 deletions(-) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 LICENSE.txt create mode 100644 package.json create mode 100644 src/actions/README.md create mode 100644 src/actions/runtime.js create mode 100644 src/client.js create mode 100644 src/components/App.js create mode 100644 src/components/Author/Author.css create mode 100644 src/components/Author/Author.js create mode 100644 src/components/Author/package.json create mode 100644 src/components/Commits/Commits.css create mode 100644 src/components/Commits/Commits.js create mode 100644 src/components/Commits/package.json create mode 100644 src/components/Header/Header.css create mode 100644 src/components/Header/Header.js create mode 100644 src/components/Header/package.json create mode 100644 src/components/Html.js create mode 100644 src/components/Layout/Layout.css create mode 100644 src/components/Layout/Layout.js create mode 100644 src/components/Layout/Layout.test.js create mode 100644 src/components/Layout/package.json create mode 100644 src/components/Main/Main.css create mode 100644 src/components/Main/Main.js create mode 100644 src/components/Main/package.json create mode 100644 src/components/SingleCommit/SingleCommit.css create mode 100644 src/components/SingleCommit/SingleCommit.js create mode 100644 src/components/SingleCommit/SingleCommit.test.js create mode 100644 src/components/SingleCommit/package.json create mode 100644 src/components/variables.css create mode 100644 src/config.js create mode 100644 src/constants/index.js create mode 100644 src/core/DOMUtils.js create mode 100644 src/core/devUtils.js create mode 100644 src/core/fetch/fetch.client.js create mode 100644 src/core/fetch/fetch.server.js create mode 100644 src/core/fetch/package.json create mode 100644 src/core/history.js create mode 100644 src/reducers/index.js create mode 100644 src/reducers/runtime.js create mode 100644 src/routes/author/Author.js create mode 100644 src/routes/author/index.js create mode 100644 src/routes/commits/Commits.js create mode 100644 src/routes/commits/index.js create mode 100644 src/routes/error/ErrorPage.css create mode 100644 src/routes/error/ErrorPage.js create mode 100644 src/routes/error/index.js create mode 100644 src/routes/home/Home.js create mode 100644 src/routes/home/Home.test.js create mode 100644 src/routes/home/index.js create mode 100644 src/routes/index.js create mode 100644 src/routes/notFound/NotFound.css create mode 100644 src/routes/notFound/NotFound.js create mode 100644 src/routes/notFound/index.js create mode 100644 src/server.js create mode 100644 src/store/configureStore.js create mode 100644 src/store/createHelpers.js create mode 100644 src/store/logger/logger.client.js create mode 100644 src/store/logger/logger.server.js create mode 100644 src/store/logger/package.json create mode 100644 test/.eslintrc create mode 100644 test/setup.js create mode 100644 tools/.eslintrc create mode 100644 tools/README.md create mode 100644 tools/build.js create mode 100644 tools/bundle.js create mode 100644 tools/clean.js create mode 100644 tools/copy.js create mode 100644 tools/deploy.js create mode 100644 tools/lib/cp.js create mode 100644 tools/lib/fs.js create mode 100644 tools/lib/markdown-loader.js create mode 100644 tools/postcss.config.js create mode 100644 tools/render.js create mode 100644 tools/run.js create mode 100644 tools/runServer.js create mode 100644 tools/start.js create mode 100644 tools/webpack.config.js diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..a882442 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,7 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1cee096 --- /dev/null +++ b/.gitignore @@ -0,0 +1,152 @@ + +# Created by https://www.gitignore.io/api/node,macos,webstorm + +### macOS ### +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Typescript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + + +### WebStorm ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/dictionaries + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml + +# Gradle: +.idea/**/gradle.xml +.idea/**/libraries + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +### WebStorm Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +.idea/sonarlint + +# End of https://www.gitignore.io/api/node,macos,webstorm \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..17193b2 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM node:6.9.5-alpine + +# Copy application files +COPY ./build /usr/src/app +WORKDIR /usr/src/app + +# Install Yarn and Node.js dependencies +RUN npm install yarn --global --no-progress --silent --depth 0 && \ +    yarn install --production --no-progress + +CMD [ "node", "server.js" ] diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..3e95f03 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License + +Copyright (c) 2014-present Konstantin Tarkus, KriaSoft LLC. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md index d07a1eb..757ae27 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ +## RUN +`npm start` for dev or `docker build -t testapp .` and `docker run testapp` + +## Notes: +https://docs.google.com/document/d/1D3lCwjdCNngTRg0Q3C0paEt7lW2jILE_TwqHeOA4m0A + ## Coding Challenge In order to be considered for this position, you must complete the following steps. @@ -8,28 +14,28 @@ In order to be considered for this position, you must complete the following ste ### Prerequisites - Please note that this will require some basic knowledge and/or the ability to learn of the following: - - [JavaScript](http://www.codecademy.com/tracks/javascript) - - [ExpressJS](http://expressjs.com/) - - [ReactJS](https://facebook.github.io/react/) - - [WebpackJS](https://webpack.js.org/) - - [ES6](http://es6-features.org/) - - Git - - [Docker](http://www.docker.com/) + - [JavaScript](http://www.codecademy.com/tracks/javascript) + - [ExpressJS](http://expressjs.com/) + - [ReactJS](https://facebook.github.io/react/) + - [WebpackJS](https://webpack.js.org/) + - [ES6](http://es6-features.org/) + - Git + - [Docker](http://www.docker.com/) - You will need to have the following installed to complete this task - - [NodeJS](http://www.nodejs.org/) - - [Docker](http://www.docker.com/) + - [NodeJS](http://www.nodejs.org/) + - [Docker](http://www.docker.com/) ## Task 1. Fork this repository 2. Create a *source* folder to contain your code. 3. In the *source* directory, please create an WebpackJS/ExpressJS/ReactJS/ES6 app that accomplishes the following: - - Connect to the [Github API](http://developer.github.com/) - - Find the [nodejs/node](https://github.com/nodejs/node) repository - - Find the most recent commits (choose at least 25 or more of the commits) - - Create a route that displays the recent commits by author. - - If the commit hash ends in a number, color that row to light blue (#E6F1F6). + - Connect to the [Github API](http://developer.github.com/) + - Find the [nodejs/node](https://github.com/nodejs/node) repository + - Find the most recent commits (choose at least 25 or more of the commits) + - Create a route that displays the recent commits by author. + - If the commit hash ends in a number, color that row to light blue (#E6F1F6). 4. Dockerize your application by writing a docker.yml file and test it by running the container locally. 5. Commit and Push your code to your new repository 6. Send us a pull request, we will review your code and get back to you @@ -38,7 +44,7 @@ In order to be considered for this position, you must complete the following ste Create the following unit tests with the testing framework of your choice: - 1. Verify that rows ending in a number are colored light blue. + 1. Verify that rows ending in a number are colored light blue. ## Once Complete 1. Commit and Push your code to your new repository @@ -48,4 +54,4 @@ Create the following unit tests with the testing framework of your choice: - When building the react application, you are free to use any type of css/html library if you choose to - You are free to write and modularize code any way you like just as long as you follow the requirements - 4 spaces for indentation! No tabs! -- If you don't know how to do something, Google is your friend! \ No newline at end of file +- If you don't know how to do something, Google is your friend! diff --git a/package.json b/package.json new file mode 100644 index 0000000..db773e6 --- /dev/null +++ b/package.json @@ -0,0 +1,214 @@ +{ + "name": "commits", + "version": "0.0.0", + "private": true, + "engines": { + "node": ">=6.5", + "npm": ">=3.10" + }, + "browserslist": [ + ">1%", + "last 4 versions", + "Firefox ESR", + "not ie < 9" + ], + "dependencies": { + "babel-polyfill": "^6.22.0", + "bluebird": "^3.4.7", + "body-parser": "^1.16.0", + "classnames": "^2.2.5", + "cookie-parser": "^1.4.3", + "core-js": "^2.4.1", + "express": "^4.14.1", + "fastclick": "^1.0.6", + "history": "^4.5.1", + "isomorphic-style-loader": "^1.1.0", + "node-fetch": "^1.6.3", + "normalize.css": "^5.0.0", + "nsp": "^2.6.3", + "pretty-error": "^2.0.2", + "query-string": "^4.3.1", + "react": "^15.4.2", + "react-dom": "^15.4.2", + "react-redux": "^5.0.2", + "redux": "^3.6.0", + "redux-logger": "^2.7.4", + "redux-thunk": "^2.1.0", + "sequelize": "^3.30.1", + "serialize-javascript": "^1.3.0", + "source-map-support": "^0.4.11", + "universal-router": "^2.0.0", + "whatwg-fetch": "^2.0.2" + }, + "devDependencies": { + "assets-webpack-plugin": "^3.5.1", + "autoprefixer": "^6.7.2", + "babel-cli": "^6.22.2", + "babel-core": "^6.22.1", + "babel-eslint": "^7.1.1", + "babel-loader": "^6.2.10", + "babel-plugin-rewire": "^1.0.0", + "babel-preset-env": "^1.1.8", + "babel-preset-react": "^6.22.0", + "babel-preset-react-optimize": "^1.0.1", + "babel-preset-stage-2": "^6.22.0", + "babel-register": "^6.22.0", + "babel-template": "^6.22.0", + "babel-types": "^6.22.0", + "browser-sync": "^2.18.7", + "chai": "^3.5.0", + "chokidar": "^1.6.1", + "css-loader": "^0.26.1", + "editorconfig-tools": "^0.1.1", + "enzyme": "^2.7.1", + "eslint": "^3.15.0", + "eslint-config-airbnb": "^14.1.0", + "eslint-loader": "^1.6.1", + "eslint-plugin-css-modules": "^2.2.0", + "eslint-plugin-import": "^2.2.0", + "eslint-plugin-jsx-a11y": "^4.0.0", + "eslint-plugin-react": "^6.9.0", + "file-loader": "^0.10.0", + "front-matter": "^2.1.2", + "glob": "^7.1.1", + "json-loader": "^0.5.4", + "lint-staged": "^3.3.0", + "markdown-it": "^8.2.2", + "mkdirp": "^0.5.1", + "mocha": "^3.2.0", + "pixrem": "^3.0.2", + "pleeease-filters": "^3.0.0", + "postcss": "^5.2.12", + "postcss-calc": "^5.3.1", + "postcss-color-function": "^3.0.0", + "postcss-custom-media": "^5.0.1", + "postcss-custom-properties": "^5.0.2", + "postcss-custom-selectors": "^3.0.0", + "postcss-flexbugs-fixes": "^2.1.0", + "postcss-loader": "^1.2.2", + "postcss-media-minmax": "^2.1.2", + "postcss-nested": "^1.0.0", + "postcss-nesting": "^2.3.1", + "postcss-partial-import": "^3.1.0", + "postcss-pseudoelements": "^3.0.0", + "postcss-selector-matches": "^2.0.5", + "postcss-selector-not": "^2.0.0", + "postcss-url": "^5.1.2", + "pre-commit": "^1.2.2", + "raw-loader": "^0.5.1", + "react-addons-test-utils": "^15.4.2", + "react-deep-force-update": "^2.0.1", + "react-hot-loader": "^3.0.0-beta.6", + "redbox-react": "^1.3.3", + "redux-mock-store": "^1.2.1", + "rimraf": "^2.5.4", + "sinon": "^2.0.0-pre.5", + "stylefmt": "^5.1.1", + "stylelint": "^7.8.0", + "stylelint-config-standard": "^16.0.0", + "url-loader": "^0.5.7", + "webpack": "^2.2.1", + "webpack-bundle-analyzer": "^2.3.0", + "webpack-dev-middleware": "^1.10.0", + "webpack-hot-middleware": "^2.16.1", + "write-file-webpack-plugin": "^3.4.2" + }, + "babel": { + "presets": [ + [ + "env", + { + "targets": { + "node": "current" + } + } + ], + "stage-2", + "react" + ], + "env": { + "test": { + "plugins": [ + "rewire" + ] + } + } + }, + "eslintConfig": { + "parser": "babel-eslint", + "extends": [ + "airbnb", + "plugin:css-modules/recommended" + ], + "plugins": [ + "css-modules" + ], + "globals": { + "__DEV__": true + }, + "env": { + "browser": true + }, + "rules": { + "import/extensions": "off", + "import/no-extraneous-dependencies": "off", + "react/jsx-filename-extension": "off", + "react/prefer-stateless-function": "off" + } + }, + "stylelint": { + "extends": "stylelint-config-standard", + "rules": { + "string-quotes": "single", + "property-no-unknown": [ + true, + { + "ignoreProperties": [ + "composes" + ] + } + ], + "selector-pseudo-class-no-unknown": [ + true, + { + "ignorePseudoClasses": [ + "global" + ] + } + ] + } + }, + "lint-staged": { + "*.{cmd,html,json,md,sh,txt,xml,yml}": [ + "editorconfig-tools fix", + "git add" + ], + "*.{js,jsx}": [ + "eslint --fix", + "git add" + ], + "*.{css,less,scss,sss}": [ + "stylefmt", + "stylelint", + "git add" + ] + }, + "scripts": { + "lint:js": "eslint src tools", + "lint:css": "stylelint \"src/**/*.{css,less,scss,sss}\"", + "lint:staged": "lint-staged", + "lint": "npm run lint:js && npm run lint:css", + "test": "mocha \"src/**/*.test.js\" --require babel-register --require test/setup.js", + "test:watch": "npm run test -- --reporter min --watch", + "nsp": "nsp check --output summary", + "clean": "babel-node tools/run clean", + "copy": "babel-node tools/run copy", + "bundle": "babel-node tools/run bundle", + "build": "babel-node tools/run build", + "build:stats": "npm run build -- --release --analyse", + "deploy": "babel-node tools/run deploy", + "render": "babel-node tools/run render", + "serve": "babel-node tools/run runServer", + "start": "babel-node tools/run start" + } +} diff --git a/src/actions/README.md b/src/actions/README.md new file mode 100644 index 0000000..be6bb8f --- /dev/null +++ b/src/actions/README.md @@ -0,0 +1,3 @@ +# Action creators + +Action Creators should go there diff --git a/src/actions/runtime.js b/src/actions/runtime.js new file mode 100644 index 0000000..1068088 --- /dev/null +++ b/src/actions/runtime.js @@ -0,0 +1,13 @@ +/* eslint-disable import/prefer-default-export */ + +import { SET_RUNTIME_VARIABLE } from '../constants'; + +export function setRuntimeVariable({ name, value }) { + return { + type: SET_RUNTIME_VARIABLE, + payload: { + name, + value, + }, + }; +} diff --git a/src/client.js b/src/client.js new file mode 100644 index 0000000..55a8333 --- /dev/null +++ b/src/client.js @@ -0,0 +1,185 @@ +/** + * React Starter Kit (https://www.reactstarterkit.com/) + * + * Copyright © 2014-present Kriasoft, LLC. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE.txt file in the root directory of this source tree. + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; +import FastClick from 'fastclick'; +import UniversalRouter from 'universal-router'; +import queryString from 'query-string'; +import { createPath } from 'history/PathUtils'; +import history from './core/history'; +import App from './components/App'; +import configureStore from './store/configureStore'; +import { updateMeta } from './core/DOMUtils'; +import { ErrorReporter, deepForceUpdate } from './core/devUtils'; + +// Global (context) variables that can be easily accessed from any React component +// https://facebook.github.io/react/docs/context.html +const context = { + // Enables critical path CSS rendering + // https://github.com/kriasoft/isomorphic-style-loader + insertCss: (...styles) => { + // eslint-disable-next-line no-underscore-dangle + const removeCss = styles.map(x => x._insertCss()); + return () => { removeCss.forEach(f => f()); }; + }, + // Initialize a new Redux store + // http://redux.js.org/docs/basics/UsageWithReact.html + store: configureStore(window.APP_STATE, { history }), +}; + +// Switch off the native scroll restoration behavior and handle it manually +// https://developers.google.com/web/updates/2015/09/history-api-scroll-restoration +const scrollPositionsHistory = {}; +if (window.history && 'scrollRestoration' in window.history) { + window.history.scrollRestoration = 'manual'; +} + +let onRenderComplete = function initialRenderComplete() { + const elem = document.getElementById('css'); + if (elem) elem.parentNode.removeChild(elem); + onRenderComplete = function renderComplete(route, location) { + document.title = route.title; + + updateMeta('description', route.description); + // Update necessary tags in at runtime here, ie: + // updateMeta('keywords', route.keywords); + // updateCustomMeta('og:url', route.canonicalUrl); + // updateCustomMeta('og:image', route.imageUrl); + // updateLink('canonical', route.canonicalUrl); + // etc. + + let scrollX = 0; + let scrollY = 0; + const pos = scrollPositionsHistory[location.key]; + if (pos) { + scrollX = pos.scrollX; + scrollY = pos.scrollY; + } else { + const targetHash = location.hash.substr(1); + if (targetHash) { + const target = document.getElementById(targetHash); + if (target) { + scrollY = window.pageYOffset + target.getBoundingClientRect().top; + } + } + } + + // Restore the scroll position if it was saved into the state + // or scroll to the given #hash anchor + // or scroll to top of the page + window.scrollTo(scrollX, scrollY); + + // Google Analytics tracking. Don't send 'pageview' event after + // the initial rendering, as it was already sent + if (window.ga) { + window.ga('send', 'pageview', createPath(location)); + } + }; +}; + +// Make taps on links and buttons work fast on mobiles +FastClick.attach(document.body); + +const container = document.getElementById('app'); +let appInstance; +let currentLocation = history.location; +let routes = require('./routes').default; + +// Re-render the app when window.location changes +async function onLocationChange(location, action) { + // Remember the latest scroll position for the previous location + scrollPositionsHistory[currentLocation.key] = { + scrollX: window.pageXOffset, + scrollY: window.pageYOffset, + }; + // Delete stored scroll position for next page if any + if (action === 'PUSH') { + delete scrollPositionsHistory[location.key]; + } + currentLocation = location; + + try { + // Traverses the list of routes in the order they are defined until + // it finds the first route that matches provided URL path string + // and whose action method returns anything other than `undefined`. + const route = await UniversalRouter.resolve(routes, { + ...context, + path: location.pathname, + query: queryString.parse(location.search), + }); + + // Prevent multiple page renders during the routing process + if (currentLocation.key !== location.key) { + return; + } + + if (route.redirect) { + history.replace(route.redirect); + return; + } + + appInstance = ReactDOM.render( + {route.component}, + container, + () => onRenderComplete(route, location), + ); + } catch (error) { + // Display the error in full-screen for development mode + if (__DEV__) { + appInstance = null; + document.title = `Error: ${error.message}`; + ReactDOM.render(, container); + throw error; + } + + console.error(error); // eslint-disable-line no-console + + // Do a full page reload if error occurs during client-side navigation + if (action && currentLocation.key === location.key) { + window.location.reload(); + } + } +} + +// Handle client-side navigation by using HTML5 History API +// For more information visit https://github.com/mjackson/history#readme +history.listen(onLocationChange); +onLocationChange(currentLocation); + +// Handle errors that might happen after rendering +// Display the error in full-screen for development mode +if (__DEV__) { + window.addEventListener('error', (event) => { + appInstance = null; + document.title = `Runtime Error: ${event.error.message}`; + ReactDOM.render(, container); + }); +} + +// Enable Hot Module Replacement (HMR) +if (module.hot) { + module.hot.accept('./routes', () => { + routes = require('./routes').default; // eslint-disable-line global-require + + if (appInstance) { + try { + // Force-update the whole tree, including components that refuse to update + deepForceUpdate(appInstance); + } catch (error) { + appInstance = null; + document.title = `Hot Update Error: ${error.message}`; + ReactDOM.render(, container); + return; + } + } + + onLocationChange(currentLocation); + }); +} diff --git a/src/components/App.js b/src/components/App.js new file mode 100644 index 0000000..4118ba8 --- /dev/null +++ b/src/components/App.js @@ -0,0 +1,68 @@ +/** + * React Starter Kit (https://www.reactstarterkit.com/) + * + * Copyright © 2014-present Kriasoft, LLC. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE.txt file in the root directory of this source tree. + */ + +import React, { Children, PropTypes } from 'react'; + +const ContextType = { + // Enables critical path CSS rendering + // https://github.com/kriasoft/isomorphic-style-loader + insertCss: PropTypes.func.isRequired, + // Integrate Redux + // http://redux.js.org/docs/basics/UsageWithReact.html + store: PropTypes.shape({ + subscribe: PropTypes.func.isRequired, + dispatch: PropTypes.func.isRequired, + getState: PropTypes.func.isRequired, + }).isRequired, +}; + +/** + * The top-level React component setting context (global) variables + * that can be accessed from all the child components. + * + * https://facebook.github.io/react/docs/context.html + * + * Usage example: + * + * const context = { + * history: createBrowserHistory(), + * store: createStore(), + * }; + * + * ReactDOM.render( + * + * + * + * + * , + * container, + * ); + */ +class App extends React.PureComponent { + + static propTypes = { + context: PropTypes.shape(ContextType).isRequired, + children: PropTypes.element.isRequired, + }; + + static childContextTypes = ContextType; + + getChildContext() { + return this.props.context; + } + + render() { + // NOTE: If you need to add or modify header, footer etc. of the app, + // please do that inside the Layout component. + return Children.only(this.props.children); + } + +} + +export default App; diff --git a/src/components/Author/Author.css b/src/components/Author/Author.css new file mode 100644 index 0000000..d200a8b --- /dev/null +++ b/src/components/Author/Author.css @@ -0,0 +1,7 @@ +.commits-list { + padding: 10px 0; +} + +a:hover { + color: red; +} diff --git a/src/components/Author/Author.js b/src/components/Author/Author.js new file mode 100644 index 0000000..d2e479a --- /dev/null +++ b/src/components/Author/Author.js @@ -0,0 +1,13 @@ +import React from 'react'; +import withStyles from 'isomorphic-style-loader/lib/withStyles'; +import s from './Author.css'; +import { SingleCommitComponent } from '../../components/SingleCommit/SingleCommit' + +export const AuthorComponent = ( {commits} ) => +
+
    + {commits.map((commit) => )} +
+
; + +export default withStyles(s)(AuthorComponent); diff --git a/src/components/Author/package.json b/src/components/Author/package.json new file mode 100644 index 0000000..1f5a43f --- /dev/null +++ b/src/components/Author/package.json @@ -0,0 +1,6 @@ +{ + "name": "Author", + "version": "0.0.0", + "private": true, + "main": "./Author.js" +} diff --git a/src/components/Commits/Commits.css b/src/components/Commits/Commits.css new file mode 100644 index 0000000..79da71d --- /dev/null +++ b/src/components/Commits/Commits.css @@ -0,0 +1,3 @@ +.root { + padding: 30px; +} diff --git a/src/components/Commits/Commits.js b/src/components/Commits/Commits.js new file mode 100644 index 0000000..dfdb0d3 --- /dev/null +++ b/src/components/Commits/Commits.js @@ -0,0 +1,14 @@ +import React from 'react'; +import withStyles from 'isomorphic-style-loader/lib/withStyles'; +import s from './Commits.css'; +import { SingleCommitComponent } from '../SingleCommit/SingleCommit' + +export const CommitsComponent = ( {commits} ) => +
+
Commits from Nodejs
+
    + {commits.map((commit) => )} +
+
; + +export default withStyles(s)(CommitsComponent); diff --git a/src/components/Commits/package.json b/src/components/Commits/package.json new file mode 100644 index 0000000..017205f --- /dev/null +++ b/src/components/Commits/package.json @@ -0,0 +1,6 @@ +{ + "name": "Commits", + "version": "0.0.0", + "private": true, + "main": "./Commits.js" +} diff --git a/src/components/Header/Header.css b/src/components/Header/Header.css new file mode 100644 index 0000000..b642280 --- /dev/null +++ b/src/components/Header/Header.css @@ -0,0 +1,7 @@ +.root { + background-color: #0366D6; + width: 100%; + color: white; + padding: 10px 30px; +} + diff --git a/src/components/Header/Header.js b/src/components/Header/Header.js new file mode 100644 index 0000000..8dac414 --- /dev/null +++ b/src/components/Header/Header.js @@ -0,0 +1,10 @@ +import React from 'react'; +import withStyles from 'isomorphic-style-loader/lib/withStyles'; +import s from './Header.css'; + +export const HeaderComponent = () => + ; + +export default withStyles(s)(HeaderComponent); diff --git a/src/components/Header/package.json b/src/components/Header/package.json new file mode 100644 index 0000000..a35793d --- /dev/null +++ b/src/components/Header/package.json @@ -0,0 +1,6 @@ +{ + "name": "Header", + "version": "0.0.0", + "private": true, + "main": "./Header.js" +} diff --git a/src/components/Html.js b/src/components/Html.js new file mode 100644 index 0000000..a00531a --- /dev/null +++ b/src/components/Html.js @@ -0,0 +1,84 @@ +/** + * React Starter Kit (https://www.reactstarterkit.com/) + * + * Copyright © 2014-present Kriasoft, LLC. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE.txt file in the root directory of this source tree. + */ + +import React, { PropTypes } from 'react'; +import serialize from 'serialize-javascript'; +import { analytics } from '../config'; + +class Html extends React.Component { + static propTypes = { + title: PropTypes.string.isRequired, + description: PropTypes.string.isRequired, + styles: PropTypes.arrayOf(PropTypes.shape({ + id: PropTypes.string.isRequired, + cssText: PropTypes.string.isRequired, + }).isRequired), + scripts: PropTypes.arrayOf(PropTypes.string.isRequired), + // eslint-disable-next-line react/forbid-prop-types + state: PropTypes.object, + children: PropTypes.string.isRequired, + }; + + static defaultProps = { + styles: [], + scripts: [], + state: null, + }; + + render() { + const { title, description, styles, scripts, state, children } = this.props; + return ( + + + + + {title} + + + {styles.map(style => +