diff --git a/frontendJS/universal-react/.babelrc b/frontendJS/universal-react/.babelrc new file mode 100644 index 0000000..203e642 --- /dev/null +++ b/frontendJS/universal-react/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["react", "es2015"] +} \ No newline at end of file diff --git a/frontendJS/universal-react/.editorconfig b/frontendJS/universal-react/.editorconfig new file mode 100644 index 0000000..b909682 --- /dev/null +++ b/frontendJS/universal-react/.editorconfig @@ -0,0 +1,20 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = false +charset = utf-8 +indent_style = tab +trim_trailing_whitespace = true + +[*.{cpp,c,h,hpp,cxx}] +insert_final_newline = true + +# Yaml files +[*.{yml,yaml}] +indent_style = space +indent_size = 4 \ No newline at end of file diff --git a/frontendJS/universal-react/.gitignore b/frontendJS/universal-react/.gitignore new file mode 100644 index 0000000..be65ac9 --- /dev/null +++ b/frontendJS/universal-react/.gitignore @@ -0,0 +1,4 @@ +dist/ +babel_cache/ +node_modules/ +public/js/bundle.js diff --git a/frontendJS/universal-react/package.json b/frontendJS/universal-react/package.json new file mode 100644 index 0000000..b126314 --- /dev/null +++ b/frontendJS/universal-react/package.json @@ -0,0 +1,27 @@ +{ + "dependencies": { + "babel-cli": "^6.11.4", + "babel-core": "^6.13.2", + "babel-preset-es2015": "^6.13.2", + "babel-preset-react": "^6.11.1", + "ejs": "^2.5.1", + "express": "^4.14.0", + "react": "^15.3.1", + "react-dom": "^15.3.1", + "react-router": "^2.6.1" + }, + "devDependencies": { + "babel-loader": "^6.2.5", + "http-server": "^0.9.0", + "webpack": "^1.13.2" + }, + "scripts": { + "start": "NODE_ENV=production babel-node src/server.js", + "build": "npm run build:client && npm run build:server", + "build:client": "NODE_ENV=production webpack -p", + "build:server": "NODE_ENV=production babel src -d dist", + "buildrun": "npm run build && npm run serve", + "clean": "rm -rf ./dist && rm -rf ./babel_cache && rm ./public/js/bundle.js", + "serve": "node dist/server.js" + } +} diff --git a/frontendJS/universal-react/public/css/style.css b/frontendJS/universal-react/public/css/style.css new file mode 100644 index 0000000..83e29e2 --- /dev/null +++ b/frontendJS/universal-react/public/css/style.css @@ -0,0 +1,246 @@ +/*! CSS reset from benfrain/app-reset */ +*,:after,:before{box-sizing:inherit}html{box-sizing:border-box} +*{user-select:none;-webkit-tap-highlight-color:rgba(255,255,255,0);-webkit-tap-highlight-color:transparent} +[contenteditable],input[type]{user-select:text}body,h1,h2,h3,h4,h5,h6,p{margin:0;font-size:1rem;font-weight:400} +a{text-decoration:none;color:inherit}b{font-weight:400}em,i{font-style:normal}a:focus,input:focus{outline:0} +fieldset,input{appearance:none;border:0;padding:0;margin:0;min-width:0;font-size:1rem;font-family:inherit} +input::-ms-clear{display:none}input[type=number]{-moz-appearance:textfield} +input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{appearance:none} +svg{display:inline-flex}img{max-width:100%;display:block} + +html { + color: #030303; + font: caption; + padding-bottom: 2em; +} + +a { + color: #1f4ba0; + text-decoration: underline; +} + +header { + padding: 2em; +} + +header .logo { + display: block; + margin: 0 auto; + max-width: 400px; + width: 100%; +} + +footer { + margin: 4em auto; + padding: 2em; + text-align: center; + max-width: 800px; + width: 100%; +} + +footer p { + line-height: 1.2em; + margin: 0 0 1em 0; +} + +.not-found { + margin: 0 auto; + max-width: 800px; + padding: 2em; + text-align: center; + width: 100%; +} + +.not-found h1 { + font-size: 3em; + font-weight: bold; +} + +.not-found h2 { + font-size: 2em; + font-weight: bold; +} + +.home .athletes-selector { + clear: both; + padding: 2em; + text-align: center; +} + +.home .athletes-selector .athlete-preview { + border: 1px solid #ccc; + box-shadow: 0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12); + display: inline-block; + margin: 0 1em 1em 0; + max-width: 200px; + padding: 0; + position: relative; + width: 100%; +} + +.home .athletes-selector .athlete-preview img { + margin: 0; + width: 100%; +} + +.home .athletes-selector .athlete-preview .name { + color: #030303; + display: inline-block; + font-size: 1.6em; + overflow: hidden; + padding: .2em; + text-align: center; + text-decoration: none; + text-overflow: ellipsis; + white-space: nowrap; + width: 100%; +} + +.home .athletes-selector .athlete-preview .medals-count { + background: #fff; + border-radius: 2px; + display: inline-block; + font-weight: bold; + margin: .2em; + padding: .2em .4em; + position: absolute; + right: 0; + text-align: center; + top: 0; + vertical-align: middle; +} + +nav.atheletes-menu { + margin: 0 auto; + max-width: 800px; + padding: 2em; + text-align: center; + width: 100%; +} + +nav.atheletes-menu a { + font-size: 1.6em; + margin: 0 1em 1em 0; +} + +nav.atheletes-menu a.active { + color: #030303; + text-decoration: none; +} + +.athlete { + border: 1px solid #ccc; + box-shadow: 0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12); + margin: 0 auto; + max-width: 800px; + width: 100%; +} + +.athlete header { + background: #ccc; + background-position: center center; + background-repeat: no-repeat; + background-size: cover; + width: 100%; + height: 200px; +} + +.athlete .picture-container { + margin: -160px 0 0 0; + padding: 0 1em 0 1em; +} + +.athlete .picture-container img { + border-radius: 4px; + border: 8px solid #fff; + box-shadow: 0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12); + display: inline; + margin: 0 0 0 1em; + width: 200px; +} + +.athlete .picture-container h2 { + display: inline; + font-size: 3em; + padding: 0 0 0 .5em; + width: auto; +} + +.athlete .flag .icon { + display: inline-block; + padding-bottom: .1em; + width: auto; +} + +.athlete .description, +.athlete .medals { + font-size: 1.6em; + padding: 1em; +} + +.athlete .medals p { + font-size: 1em; +} + +.athlete .medals li { + list-style: none; +} + +.athlete .medals .symbol { + border-radius: 50%; + display: inline-block; + font-size: .8em; + height: 1.6em; + justify-content: center; + margin: 5px; + text-align: center; + width: 1.6em; +} + +.athlete .medals .symbol.symbol-G { + color: #daa520; + background-color: #fff6de; + border: 2px solid #daa520; +} + +.athlete .medals .symbol.symbol-S { + color: #383738; + background-color: #b9b5b5; + border: 2px solid #383738; +} + +.athlete .medals .symbol.symbol-B { + color: #6b1919; + background-color: #ea96a1; + border: 2px solid #6E1924; +} + +.navigateBack { + font-size: 1.6em; + padding: 2em; + text-align: center; + text-decoration: none; +} + +#abar { + bottom: 0; + left: 0; + position: fixed; + width: 100%; +} + +#abar a { + background: #ffa500; + color: #000; + display: block; + font-weight: bold; + margin: 0; + padding: 1em; + text-align: center; + text-decoration: none; + width: 100%; +} + +#abar a:hover { + text-decoration: underline; +} diff --git a/frontendJS/universal-react/public/favicon.ico b/frontendJS/universal-react/public/favicon.ico new file mode 100644 index 0000000..c6fc0b4 Binary files /dev/null and b/frontendJS/universal-react/public/favicon.ico differ diff --git a/frontendJS/universal-react/public/img/driulis-gonzalez-cover.jpg b/frontendJS/universal-react/public/img/driulis-gonzalez-cover.jpg new file mode 100644 index 0000000..b85f6ab Binary files /dev/null and b/frontendJS/universal-react/public/img/driulis-gonzalez-cover.jpg differ diff --git a/frontendJS/universal-react/public/img/driulis-gonzalez.jpg b/frontendJS/universal-react/public/img/driulis-gonzalez.jpg new file mode 100644 index 0000000..9c8e84d Binary files /dev/null and b/frontendJS/universal-react/public/img/driulis-gonzalez.jpg differ diff --git a/frontendJS/universal-react/public/img/flag-cu.png b/frontendJS/universal-react/public/img/flag-cu.png new file mode 100755 index 0000000..083f1d6 Binary files /dev/null and b/frontendJS/universal-react/public/img/flag-cu.png differ diff --git a/frontendJS/universal-react/public/img/flag-fr.png b/frontendJS/universal-react/public/img/flag-fr.png new file mode 100755 index 0000000..8332c4e Binary files /dev/null and b/frontendJS/universal-react/public/img/flag-fr.png differ diff --git a/frontendJS/universal-react/public/img/flag-jp.png b/frontendJS/universal-react/public/img/flag-jp.png new file mode 100755 index 0000000..325fbad Binary files /dev/null and b/frontendJS/universal-react/public/img/flag-jp.png differ diff --git a/frontendJS/universal-react/public/img/flag-nl.png b/frontendJS/universal-react/public/img/flag-nl.png new file mode 100755 index 0000000..fe44791 Binary files /dev/null and b/frontendJS/universal-react/public/img/flag-nl.png differ diff --git a/frontendJS/universal-react/public/img/flag-uz.png b/frontendJS/universal-react/public/img/flag-uz.png new file mode 100755 index 0000000..fef5dc1 Binary files /dev/null and b/frontendJS/universal-react/public/img/flag-uz.png differ diff --git a/frontendJS/universal-react/public/img/logo-judo-heroes.png b/frontendJS/universal-react/public/img/logo-judo-heroes.png new file mode 100644 index 0000000..836d97f Binary files /dev/null and b/frontendJS/universal-react/public/img/logo-judo-heroes.png differ diff --git a/frontendJS/universal-react/public/img/mark-huizinga-cover.jpg b/frontendJS/universal-react/public/img/mark-huizinga-cover.jpg new file mode 100644 index 0000000..0b0c026 Binary files /dev/null and b/frontendJS/universal-react/public/img/mark-huizinga-cover.jpg differ diff --git a/frontendJS/universal-react/public/img/mark-huizinga.jpg b/frontendJS/universal-react/public/img/mark-huizinga.jpg new file mode 100644 index 0000000..c47a9ec Binary files /dev/null and b/frontendJS/universal-react/public/img/mark-huizinga.jpg differ diff --git a/frontendJS/universal-react/public/img/medal.png b/frontendJS/universal-react/public/img/medal.png new file mode 100644 index 0000000..ef1b08b Binary files /dev/null and b/frontendJS/universal-react/public/img/medal.png differ diff --git a/frontendJS/universal-react/public/img/rishod-sobirov-cover.jpg b/frontendJS/universal-react/public/img/rishod-sobirov-cover.jpg new file mode 100644 index 0000000..64b5c48 Binary files /dev/null and b/frontendJS/universal-react/public/img/rishod-sobirov-cover.jpg differ diff --git a/frontendJS/universal-react/public/img/rishod-sobirov.jpg b/frontendJS/universal-react/public/img/rishod-sobirov.jpg new file mode 100644 index 0000000..3f425c5 Binary files /dev/null and b/frontendJS/universal-react/public/img/rishod-sobirov.jpg differ diff --git a/frontendJS/universal-react/public/img/ryoko-tani-cover.jpg b/frontendJS/universal-react/public/img/ryoko-tani-cover.jpg new file mode 100644 index 0000000..6b3367a Binary files /dev/null and b/frontendJS/universal-react/public/img/ryoko-tani-cover.jpg differ diff --git a/frontendJS/universal-react/public/img/ryoko-tani.jpg b/frontendJS/universal-react/public/img/ryoko-tani.jpg new file mode 100644 index 0000000..c89d2ed Binary files /dev/null and b/frontendJS/universal-react/public/img/ryoko-tani.jpg differ diff --git a/frontendJS/universal-react/public/img/teddy-riner-cover.jpg b/frontendJS/universal-react/public/img/teddy-riner-cover.jpg new file mode 100644 index 0000000..04784bc Binary files /dev/null and b/frontendJS/universal-react/public/img/teddy-riner-cover.jpg differ diff --git a/frontendJS/universal-react/public/img/teddy-riner.jpg b/frontendJS/universal-react/public/img/teddy-riner.jpg new file mode 100644 index 0000000..c96feb5 Binary files /dev/null and b/frontendJS/universal-react/public/img/teddy-riner.jpg differ diff --git a/frontendJS/universal-react/public/index.html b/frontendJS/universal-react/public/index.html new file mode 100644 index 0000000..6042f54 --- /dev/null +++ b/frontendJS/universal-react/public/index.html @@ -0,0 +1,13 @@ + + + + + + Judo Heroes - A Universal Javascript demo application with React + + + +
+ + + \ No newline at end of file diff --git a/frontendJS/universal-react/src/app-client.js b/frontendJS/universal-react/src/app-client.js new file mode 100644 index 0000000..4104fa6 --- /dev/null +++ b/frontendJS/universal-react/src/app-client.js @@ -0,0 +1,5 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import AppRoutes from './components/AppRoutes'; + +ReactDOM.render(, document.getElementById('main')); \ No newline at end of file diff --git a/frontendJS/universal-react/src/components/AppRoutes.js b/frontendJS/universal-react/src/components/AppRoutes.js new file mode 100644 index 0000000..3d2f630 --- /dev/null +++ b/frontendJS/universal-react/src/components/AppRoutes.js @@ -0,0 +1,13 @@ +import React from 'react'; +import { Router, browserHistory } from 'react-router'; +import routes from '../routes'; + +class AppRoutes extends React.Component { + render() { + return ( + window.scrollTo(0, 0)} /> + ); + } +} + +export default AppRoutes; \ No newline at end of file diff --git a/frontendJS/universal-react/src/components/AthleteMenu.js b/frontendJS/universal-react/src/components/AthleteMenu.js new file mode 100644 index 0000000..2b58a57 --- /dev/null +++ b/frontendJS/universal-react/src/components/AthleteMenu.js @@ -0,0 +1,19 @@ +import React from 'react'; +import { Link } from 'react-router'; +import athletes from '../data/athletes'; + +class AthleteMenu extends React.Component { + render() { + return ( + + ); + } +} + +export default AthleteMenu; \ No newline at end of file diff --git a/frontendJS/universal-react/src/components/AthletePage.js b/frontendJS/universal-react/src/components/AthletePage.js new file mode 100644 index 0000000..aedba3a --- /dev/null +++ b/frontendJS/universal-react/src/components/AthletePage.js @@ -0,0 +1,48 @@ +import React from 'react'; +import { Link } from 'react-router'; +import NotFoundPage from './NotFoundPage'; +import AthleteMenu from './AthleteMenu'; +import Medal from './Medal'; +import Flag from './Flag'; +import athletes from '../data/athletes'; + +class AthletePage extends React.Component { + render() { + const id = this.props.params.id; + const athlete = athletes.filter(athlete => athlete.id === id)[0]; + if ( ! athlete) { + return + } + const headerStyle = { + backgroundImage: `url(/img/${athlete.cover})` + }; + + return ( +
+ +
+
+
+ +

{athlete.name}

+
+
+ Olympic medalist from , + born in {athlete.birth} (Find out more on Wikipedia). +
+
+

Winner of {athlete.medals.length} medals:

+
    { + athlete.medals.map((medal, i) => ) + }
+
+
+
+ « Back to the index +
+
+ ); + } +} + +export default AthletePage; \ No newline at end of file diff --git a/frontendJS/universal-react/src/components/AthletePreview.js b/frontendJS/universal-react/src/components/AthletePreview.js new file mode 100644 index 0000000..1b933b5 --- /dev/null +++ b/frontendJS/universal-react/src/components/AthletePreview.js @@ -0,0 +1,21 @@ +import React from 'react'; +import { Link } from 'react-router'; + +class AthletePreview extends React.Component { + render() { + return ( + +
+ +

{this.props.name}

+ + + {this.props.medals.length} + +
+ + ); + } +} + +export default AthletePreview; \ No newline at end of file diff --git a/frontendJS/universal-react/src/components/Flag.js b/frontendJS/universal-react/src/components/Flag.js new file mode 100644 index 0000000..ae56fdb --- /dev/null +++ b/frontendJS/universal-react/src/components/Flag.js @@ -0,0 +1,40 @@ +import React from 'react'; + +const data = { + cu: { + name: 'Cuba', + icon: 'flag-cu.png' + }, + fr: { + name: 'France', + icon: 'flag-fr.png' + }, + jp: { + name: 'Japan', + icon: 'flag-jp.png' + }, + nl: { + name: 'Netherlands', + icon: 'flag-nl.png' + }, + uz: { + name: 'Uzbekistan', + icon: 'flag-uz.png' + } +}; + +class Flag extends React.Component { + render() { + const name = data[this.props.code].name; + const icon = data[this.props.code].icon; + + return ( + + +  {this.props.showName && {name}} + + ); + } +} + +export default Flag; \ No newline at end of file diff --git a/frontendJS/universal-react/src/components/IndexPage.js b/frontendJS/universal-react/src/components/IndexPage.js new file mode 100644 index 0000000..492e6a5 --- /dev/null +++ b/frontendJS/universal-react/src/components/IndexPage.js @@ -0,0 +1,17 @@ +import React from 'react'; +import AthletePreview from './AthletePreview'; +import athletes from '../data/athletes'; + +class IndexPage extends React.Component { + render() { + return ( +
+
+ {athletes.map(athleteData => )} +
+
+ ); + } +} + +export default IndexPage; \ No newline at end of file diff --git a/frontendJS/universal-react/src/components/Layout.js b/frontendJS/universal-react/src/components/Layout.js new file mode 100644 index 0000000..f6fec2c --- /dev/null +++ b/frontendJS/universal-react/src/components/Layout.js @@ -0,0 +1,24 @@ +import React from 'react'; +import { Link } from 'react-router'; + +class Layout extends React.Component { + render() { + return ( +
+
+ + + +
+
{this.props.children}
+
+

+ This is a demo app to showcase universal rendering and routing with React and Express. +

+
+
+ ); + } +} + +export default Layout; \ No newline at end of file diff --git a/frontendJS/universal-react/src/components/Medal.js b/frontendJS/universal-react/src/components/Medal.js new file mode 100644 index 0000000..7c21b38 --- /dev/null +++ b/frontendJS/universal-react/src/components/Medal.js @@ -0,0 +1,23 @@ +import React from 'react'; + +const typeMap = { + G: 'Gold', + S: 'Silver', + B: 'Bronze' +}; + +class Medal extends React.Component { + render() { + return ( +
  • + {this.props.type} + {this.props.year} + {this.props.city} + ({this.props.event}) + {this.props.category} +
  • + ); + } +} + +export default Medal; \ No newline at end of file diff --git a/frontendJS/universal-react/src/components/NotFoundPage.js b/frontendJS/universal-react/src/components/NotFoundPage.js new file mode 100644 index 0000000..c2b054d --- /dev/null +++ b/frontendJS/universal-react/src/components/NotFoundPage.js @@ -0,0 +1,18 @@ +import React from 'react'; +import { Link } from 'react-router'; + +class NotFoundPage extends React.Component { + render() { + return ( +
    +

    404

    +

    Page not found!

    +

    + Go back to the main page +

    +
    + ); + } +} + +export default NotFoundPage; \ No newline at end of file diff --git a/frontendJS/universal-react/src/data/athletes.js b/frontendJS/universal-react/src/data/athletes.js new file mode 100644 index 0000000..f773b97 --- /dev/null +++ b/frontendJS/universal-react/src/data/athletes.js @@ -0,0 +1,134 @@ +"use strict"; + +const athletes = [ + { + 'id': 'driulis-gonzalez', + 'name': 'Driulis González', + 'country': 'cu', + 'birth': '1973', + 'image': 'driulis-gonzalez.jpg', + 'cover': 'driulis-gonzalez-cover.jpg', + 'link': 'https://en.wikipedia.org/wiki/Driulis_González', + 'medals': [ + { 'year': '1992', 'type': 'B', 'city': 'Barcelona', 'event': 'Olympic Games', 'category': '-57kg' }, + { 'year': '1993', 'type': 'B', 'city': 'Hamilton', 'event': 'World Championships', 'category': '-57kg' }, + { 'year': '1995', 'type': 'G', 'city': 'Chiba', 'event': 'World Championships', 'category': '-57kg' }, + { 'year': '1995', 'type': 'G', 'city': 'Mar del Plata', 'event': 'Pan American Games', 'category': '-57kg' }, + { 'year': '1996', 'type': 'G', 'city': 'Atlanta', 'event': 'Olympic Games', 'category': '-57kg' }, + { 'year': '1997', 'type': 'S', 'city': 'Osaka', 'event': 'World Championships', 'category': '-57kg' }, + { 'year': '1999', 'type': 'G', 'city': 'Birmingham', 'event': 'World Championships', 'category': '-57kg' }, + { 'year': '2000', 'type': 'S', 'city': 'Sydney', 'event': 'Olympic Games', 'category': '-57kg' }, + { 'year': '2003', 'type': 'G', 'city': 'S Domingo', 'event': 'Pan American Games', 'category': '-63kg' }, + { 'year': '2003', 'type': 'S', 'city': 'Osaka', 'event': 'World Championships', 'category': '-63kg' }, + { 'year': '2004', 'type': 'B', 'city': 'Athens', 'event': 'Olympic Games', 'category': '-63kg' }, + { 'year': '2005', 'type': 'B', 'city': 'Cairo', 'event': 'World Championships', 'category': '-63kg' }, + { 'year': '2006', 'type': 'G', 'city': 'Cartagena', 'event': 'Central American and Caribbean Games', 'category': '-63kg' }, + { 'year': '2006', 'type': 'G', 'city': 'Cartagena', 'event': 'Central American and Caribbean Games', 'category': 'Tema' }, + { 'year': '2007', 'type': 'G', 'city': 'Rio de Janeiro', 'event': 'Pan American Games', 'category': '-63kg' }, + { 'year': '2007', 'type': 'G', 'city': 'Rio de Janeiro', 'event': 'World Championships', 'category': '-63kg' }, + ], + }, + { + 'id': 'mark-huizinga', + 'name': 'Mark Huizinga', + 'country': 'nl', + 'birth': '1973', + 'image': 'mark-huizinga.jpg', + 'cover': 'mark-huizinga-cover.jpg', + 'link': 'https://en.wikipedia.org/wiki/Mark_Huizinga', + 'medals': [ + { 'year': '1994', 'type': 'B', 'city': 'Gdansk', 'event': 'European Championships', 'category': '-78kg' }, + { 'year': '1996', 'type': 'B', 'city': 'Atlanta', 'event': 'Olympic Games', 'category': '-86kg' }, + { 'year': '1996', 'type': 'G', 'city': 'The Hague', 'event': 'European Championships', 'category': '-86kg' }, + { 'year': '1997', 'type': 'G', 'city': 'Oostende', 'event': 'European Championships', 'category': '-86kg' }, + { 'year': '1998', 'type': 'G', 'city': 'Oviedo', 'event': 'European Championships', 'category': '-90kg' }, + { 'year': '1999', 'type': 'B', 'city': 'Bratislava', 'event': 'European Championships', 'category': '-90kg' }, + { 'year': '2000', 'type': 'G', 'city': 'Sydney', 'event': 'Olympic Games', 'category': '-90kg' }, + { 'year': '2000', 'type': 'S', 'city': 'Wroclaw', 'event': 'European Championships', 'category': '-90kg' }, + { 'year': '2001', 'type': 'G', 'city': 'Paris', 'event': 'European Championships', 'category': '-90kg' }, + { 'year': '2002', 'type': 'B', 'city': 'Maribor', 'event': 'European Championships', 'category': '-90kg' }, + { 'year': '2003', 'type': 'B', 'city': 'Düsseldorf', 'event': 'European Championships', 'category': '-90kg' }, + { 'year': '2004', 'type': 'B', 'city': 'Athens', 'event': 'Olympic Games', 'category': '-90kg' }, + { 'year': '2004', 'type': 'S', 'city': 'Bucharest', 'event': 'European Championships', 'category': '-90kg' }, + { 'year': '2005', 'type': 'B', 'city': 'Cairo', 'event': 'World Championships', 'category': '-90kg' }, + { 'year': '2005', 'type': 'B', 'city': 'Rotterdam', 'event': 'European Championships', 'category': '-90kg' }, + { 'year': '2008', 'type': 'G', 'city': 'Lisbon', 'event': 'European Championships', 'category': '-90kg' }, + ], + }, + { + 'id': 'rishod-sobirov', + 'name': 'Rishod Sobirov', + 'country': 'uz', + 'birth': '1986', + 'image': 'rishod-sobirov.jpg', + 'cover': 'rishod-sobirov-cover.jpg', + 'link': 'https://en.wikipedia.org/wiki/Rishod_Sobirov', + 'medals': [ + { 'year': '2007', 'type': 'S', 'city': 'Kuwait City', 'event': 'Asian Championships', 'category': '-60kg' }, + { 'year': '2008', 'type': 'B', 'city': 'Beijing', 'event': 'Olympic Games', 'category': '-60kg' }, + { 'year': '2010', 'type': 'G', 'city': 'Tokyo', 'event': 'World Championships', 'category': '-60kg' }, + { 'year': '2011', 'type': 'G', 'city': 'Paris', 'event': 'World Championships', 'category': '-60kg' }, + { 'year': '2012', 'type': 'B', 'city': 'London', 'event': 'Olympic Games', 'category': '-60kg' }, + { 'year': '2015', 'type': 'B', 'city': 'Astana', 'event': 'World Championships', 'category': '-66kg' }, + { 'year': '2016', 'type': 'B', 'city': 'Rio de Janeiro', 'event': 'Olympic Games', 'category': '-66kg' }, + ], + }, + { + 'id': 'ryoko-tani', + 'name': 'Ryoko Tani', + 'country': 'jp', + 'birth': '1975', + 'image': 'ryoko-tani.jpg', + 'cover': 'ryoko-tani-cover.jpg', + 'link': 'https://en.wikipedia.org/wiki/Ryoko_Tani', + 'medals': [ + { 'year': '1991', 'type': 'B', 'city': 'Barcelona', 'event': 'World Championships', 'category': '-48kg' }, + { 'year': '1991', 'type': 'B', 'city': 'Osaka', 'event': 'Asian Championships', 'category': '-48kg' }, + { 'year': '1992', 'type': 'S', 'city': 'Barcelona', 'event': 'Olympic Games', 'category': '-48kg' }, + { 'year': '1993', 'type': 'G', 'city': 'Hamilton', 'event': 'World Championships', 'category': '-48kg' }, + { 'year': '1994', 'type': 'G', 'city': 'Hiroshima', 'event': 'Asian Games', 'category': '-48kg' }, + { 'year': '1995', 'type': 'G', 'city': 'Chiba', 'event': 'World Championships', 'category': '-48kg' }, + { 'year': '1995', 'type': 'G', 'city': 'Fukuoka', 'event': 'Universiade', 'category': '-48kg' }, + { 'year': '1996', 'type': 'S', 'city': 'Atlanta', 'event': 'Olympic Games', 'category': '-48kg' }, + { 'year': '1997', 'type': 'G', 'city': 'Paris', 'event': 'World Championships', 'category': '-48kg' }, + { 'year': '1999', 'type': 'G', 'city': 'Birmingham', 'event': 'World Championships', 'category': '-48kg' }, + { 'year': '2000', 'type': 'G', 'city': 'Sydney', 'event': 'Olympic Games', 'category': '-48kg' }, + { 'year': '2001', 'type': 'G', 'city': 'Munich', 'event': 'World Championships', 'category': '-48kg' }, + { 'year': '2003', 'type': 'G', 'city': 'Osaka', 'event': 'World Championships', 'category': '-48kg' }, + { 'year': '2004', 'type': 'G', 'city': 'Athens', 'event': 'Olympic Games', 'category': '-48kg' }, + { 'year': '2007', 'type': 'G', 'city': 'Rio de Janeiro', 'event': 'World Championships', 'category': '-48kg' }, + { 'year': '2008', 'type': 'B', 'city': 'Beijing', 'event': 'Olympic Games', 'category': '-48kg' }, + ], + }, + { + 'id': 'teddy-riner', + 'name': 'Teddy Riner', + 'country': 'fr', + 'birth': '1989', + 'image': 'teddy-riner.jpg', + 'cover': 'teddy-riner-cover.jpg', + 'link': 'https://en.wikipedia.org/wiki/Teddy_Riner', + 'medals': [ + { 'year': '2007', 'type': 'G', 'city': 'Belgrade', 'event': 'European Championships', 'category': '+100kg' }, + { 'year': '2007', 'type': 'G', 'city': 'Rio de Janeiro', 'event': 'World Championships', 'category': '+100kg' }, + { 'year': '2008', 'type': 'B', 'city': 'Beijing', 'event': 'Olympic Games', 'category': '+100kg' }, + { 'year': '2008', 'type': 'G', 'city': 'Levallois-Perret', 'event': 'World Openweight Championships', 'category': 'Open' }, + { 'year': '2009', 'type': 'G', 'city': 'Pescara', 'event': 'Mediterranean Games', 'category': '+100kg' }, + { 'year': '2009', 'type': 'G', 'city': 'Rotterdam', 'event': 'World Championships', 'category': '+100kg' }, + { 'year': '2010', 'type': 'G', 'city': 'Tokyo', 'event': 'World Championships', 'category': '+100kg' }, + { 'year': '2010', 'type': 'S', 'city': 'Tokyo', 'event': 'World Championships', 'category': 'Open' }, + { 'year': '2011', 'type': 'G', 'city': 'Istanbul', 'event': 'European Championships', 'category': '+100kg' }, + { 'year': '2011', 'type': 'G', 'city': 'Paris', 'event': 'World Championships', 'category': '+100kg' }, + { 'year': '2012', 'type': 'G', 'city': 'London', 'event': 'Olympic Games', 'category': '+100kg' }, + { 'year': '2013', 'type': 'G', 'city': 'Budapest', 'event': 'European Championships', 'category': '+100kg' }, + { 'year': '2013', 'type': 'G', 'city': 'Rio de Janeiro', 'event': 'World Championships', 'category': '+100kg' }, + { 'year': '2014', 'type': 'G', 'city': 'Chelyabinsk', 'event': 'World Championships', 'category': '+100kg' }, + { 'year': '2014', 'type': 'G', 'city': 'Montpellier', 'event': 'European Championships', 'category': '+100kg' }, + { 'year': '2015', 'type': 'G', 'city': 'Astana', 'event': 'World Championships', 'category': '+100kg' }, + { 'year': '2016', 'type': 'G', 'city': 'Kazan', 'event': 'European Championships', 'category': '+100kg' }, + { 'year': '2016', 'type': 'G', 'city': 'Rio de Janeiro', 'event': 'Olympic Games', 'category': '+100kg' }, + ], + } +]; + +export default athletes; diff --git a/frontendJS/universal-react/src/routes.js b/frontendJS/universal-react/src/routes.js new file mode 100644 index 0000000..d5854db --- /dev/null +++ b/frontendJS/universal-react/src/routes.js @@ -0,0 +1,16 @@ +import React from 'react'; +import { Route, IndexRoute } from 'react-router'; +import Layout from './components/Layout'; +import IndexPage from './components/IndexPage'; +import AthletePage from './components/AthletePage'; +import NotFoundPage from './components/NotFoundPage'; + +const routes = ( + + + + + +); + +export default routes; \ No newline at end of file diff --git a/frontendJS/universal-react/src/server.js b/frontendJS/universal-react/src/server.js new file mode 100644 index 0000000..c9f4eaf --- /dev/null +++ b/frontendJS/universal-react/src/server.js @@ -0,0 +1,56 @@ +import path from 'path'; +import { Server } from 'http'; +import Express from 'express'; +import React from 'react'; +import { renderToString } from 'react-dom/server'; +import { match, RouterContext } from 'react-router'; +import routes from './routes'; +import NotFoundPage from './components/NotFoundPage'; + +// initialize the server and configure support for ejs templates +const app = new Express(); +const server = new Server(app); +app.set('view engine', 'ejs'); +app.set('views', path.join(__dirname, '..', 'views')); + +// define the folder that will be used for public assets +app.use(Express.static(path.join(__dirname, '..', 'public'))); + +// universal routing and rendering +app.get('*', (req, res) => { + match({routes, location: req.url}, (err, redirectLocation, renderProps) => { + // Directly send errors + if (err) { + return res.status(500).send(err.message); + } + + // Propagate redirects to the browser + if (redirectLocation) { + return res.redirect(302, redirectLocation.pathname + redirectLocation.search); + } + + // generate the React markup for the current route + let markup; + if (renderProps) { + // if the current route matched, we have renderProps + markup = renderToString(); + } else { + markup = renderToString(); + res.status(404); + } + + // render the index template with the embedded React markup + return res.render('index', { markup:markup }); + }); +}); + +// start the server +const port = process.env.PORT || 3000; +const env = process.env.NODE_ENV || 'production'; + +server.listen(port, err => { + if (err) { + return console.error(err); + } + console.info(`Server running on http://localhost:${port} [${env}]`); +}); \ No newline at end of file diff --git a/frontendJS/universal-react/views/index.ejs b/frontendJS/universal-react/views/index.ejs new file mode 100644 index 0000000..9129e98 --- /dev/null +++ b/frontendJS/universal-react/views/index.ejs @@ -0,0 +1,14 @@ + + + + + + Judo Heroes - A Universal Javascript demo application with React + + + + +
    <%- markup -%>
    + + + \ No newline at end of file diff --git a/frontendJS/universal-react/webpack.config.js b/frontendJS/universal-react/webpack.config.js new file mode 100644 index 0000000..406a076 --- /dev/null +++ b/frontendJS/universal-react/webpack.config.js @@ -0,0 +1,36 @@ +const webpack = require('webpack'); +const path = require('path'); + +module.exports = { + entry: path.join(__dirname, 'src', 'app-client.js'), + output: { + path: path.join(__dirname, 'public', 'js'), + filename: 'bundle.js' + }, + module: { + loaders: [{ + test: path.join(__dirname, 'src'), + loader: ['babel-loader'], + query: { + cacheDirectory: 'babel_cache', + presets: ['react', 'es2015'] + } + }] + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV) + }), + new webpack.optimize.DedupePlugin(), + new webpack.optimize.OccurrenceOrderPlugin(), + new webpack.optimize.UglifyJsPlugin({ + compress: { + warnings: false + }, + mangle: true, + sourcemap: false, + beautify: false, + dead_code: true + }), + ] +}; \ No newline at end of file