├── .gitignore ├── LICENCE.txt ├── api ├── .gitignore ├── apidoc.json ├── doc │ ├── api_data.js │ ├── api_data.json │ ├── api_project.js │ ├── api_project.json │ ├── css │ │ └── style.css │ ├── img │ │ ├── favicon.ico │ │ ├── glyphicons-halflings-white.png │ │ └── glyphicons-halflings.png │ ├── index.html │ ├── locales │ │ ├── ca.js │ │ ├── de.js │ │ ├── es.js │ │ ├── fr.js │ │ ├── locale.js │ │ ├── nl.js │ │ ├── pl.js │ │ ├── pt_br.js │ │ ├── ru.js │ │ ├── zh.js │ │ └── zh_cn.js │ ├── main.js │ ├── utils │ │ ├── handlebars_helper.js │ │ └── send_sample_request.js │ └── vendor │ │ ├── bootstrap-responsive.min.css │ │ ├── bootstrap.min.css │ │ ├── bootstrap.min.js │ │ ├── diff_match_patch.min.js │ │ ├── handlebars.min.js │ │ ├── jquery.min.js │ │ ├── lodash.min.js │ │ ├── path-to-regexp │ │ ├── LICENSE │ │ └── index.js │ │ ├── polyfill.js │ │ ├── prettify.css │ │ ├── prettify │ │ ├── lang-apollo.js │ │ ├── lang-basic.js │ │ ├── lang-clj.js │ │ ├── lang-css.js │ │ ├── lang-dart.js │ │ ├── lang-erlang.js │ │ ├── lang-go.js │ │ ├── lang-hs.js │ │ ├── lang-lisp.js │ │ ├── lang-llvm.js │ │ ├── lang-lua.js │ │ ├── lang-matlab.js │ │ ├── lang-ml.js │ │ ├── lang-mumps.js │ │ ├── lang-n.js │ │ ├── lang-pascal.js │ │ ├── lang-proto.js │ │ ├── lang-r.js │ │ ├── lang-rd.js │ │ ├── lang-scala.js │ │ ├── lang-sql.js │ │ ├── lang-tcl.js │ │ ├── lang-tex.js │ │ ├── lang-vb.js │ │ ├── lang-vhdl.js │ │ ├── lang-wiki.js │ │ ├── lang-xq.js │ │ ├── lang-yaml.js │ │ ├── prettify.css │ │ ├── prettify.js │ │ └── run_prettify.js │ │ ├── require.min.js │ │ ├── semver.min.js │ │ └── webfontloader.js ├── package.json └── src │ ├── data │ ├── bordeaux-wines.json │ ├── burgundy-wines.json │ ├── champagne-wines.json │ ├── images │ │ ├── aligote.png │ │ ├── arcins.png │ │ ├── bel-air.png │ │ ├── boisson.png │ │ ├── bollinger-special-cuvee.png │ │ ├── bonnamy.png │ │ ├── chantalouette.png │ │ ├── charme-cos-labory.png │ │ ├── cheval-noir.png │ │ ├── chevrol-bel-air.png │ │ ├── clarendelle.png │ │ ├── cormeil-figeac.png │ │ ├── cote-beaune-village.png │ │ ├── deutz.png │ │ ├── domaine-chatenoy.png │ │ ├── domaine-desoucherie.png │ │ ├── domaine-petit-coteau.png │ │ ├── fleur-haut-bages-liberal.png │ │ ├── jaillance.png │ │ ├── la-noe.png │ │ ├── la-roche.png │ │ ├── lacaussade-saint-martin.png │ │ ├── ladoix-pierre-andre.png │ │ ├── laniote.png │ │ ├── lanson-blanc-de-blanc.png │ │ ├── lanson.png │ │ ├── latour-camblanes.png │ │ ├── laurent-perrier.png │ │ ├── les-cailloux.png │ │ ├── les-champs-clos-blanc.png │ │ ├── les-champs-clos-rouge.png │ │ ├── les-hauts-de-tour-prignac.png │ │ ├── les-vaillons.png │ │ ├── lestage.png │ │ ├── macon-lugny.png │ │ ├── marsannay.png │ │ ├── moet-chandon.png │ │ ├── mouton-cadet-rose.png │ │ ├── mouton-cadet.png │ │ ├── oratoire-chasse-spleen.png │ │ ├── patache-d-aux.png │ │ ├── philippe-de-valois.png │ │ ├── pol-roger.png │ │ ├── rahoul.png │ │ ├── reserve-des-vignerons-blanc.png │ │ ├── reserve-des-vignerons-rouge.png │ │ ├── roc-de-boissac.png │ │ ├── teynac.png │ │ ├── thomas-barton-reserve.png │ │ ├── tour-des-termes.png │ │ └── vin-de-messe.png │ └── loire-wines.json │ └── server.js ├── dependencies ├── .gitignore └── package.json ├── deps.js ├── install.sh ├── print ├── index.html ├── pdf │ ├── all.pdf │ ├── index.pdf │ ├── step-0.pdf │ ├── step-1.pdf │ ├── step-2.pdf │ ├── step-3.pdf │ ├── step-4.pdf │ ├── step-5.pdf │ ├── step-6.pdf │ ├── step-7.pdf │ └── step-8.pdf ├── step-0 │ └── index.html ├── step-1 │ └── index.html ├── step-2 │ └── index.html ├── step-3 │ └── index.html ├── step-4 │ └── index.html ├── step-5 │ └── index.html ├── step-6 │ └── index.html ├── step-7 │ └── index.html └── step-8 │ └── index.html ├── readme.md ├── step-0-done ├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── package.json ├── public │ ├── css │ │ └── main.css │ ├── img │ │ ├── chevrol-bel-air.png │ │ └── react.png │ ├── index.html │ └── js │ │ └── .gitkeep ├── readme.md ├── src │ ├── app.js │ └── components │ │ └── wine.js └── webpack.config.js ├── step-0 └── readme.md ├── step-1-done ├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── package.json ├── public │ ├── css │ │ ├── avalanche.css │ │ └── main.css │ ├── img │ │ ├── chevrol-bel-air.png │ │ └── react.png │ ├── index.html │ └── js │ │ └── .gitkeep ├── readme.md ├── src │ ├── app.js │ └── components │ │ └── wine.js ├── tests │ ├── bootstrap.js │ ├── components │ │ └── wine.spec.js │ └── index.js └── webpack.config.js ├── step-1 ├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── package.json ├── public │ ├── css │ │ └── main.css │ ├── img │ │ ├── chevrol-bel-air.png │ │ └── react.png │ ├── index.html │ └── js │ │ └── .gitkeep ├── readme.md ├── src │ ├── app.js │ └── components │ │ └── wine.js ├── tests │ ├── bootstrap.js │ └── index.js └── webpack.config.js ├── step-2-done ├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── package.json ├── public │ ├── css │ │ ├── avalanche.css │ │ └── main.css │ ├── img │ │ ├── chevrol-bel-air.png │ │ └── react.png │ ├── index.html │ └── js │ │ └── .gitkeep ├── readme.md ├── src │ ├── app.js │ └── components │ │ ├── regions.js │ │ ├── wine-app.js │ │ ├── wine-list.js │ │ └── wine.js ├── tests │ ├── bootstrap.js │ ├── components │ │ ├── regions.spec.js │ │ ├── wine-app.spec.js │ │ ├── wine-list.spec.js │ │ └── wine.spec.js │ └── index.js └── webpack.config.js ├── step-2 ├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── package.json ├── public │ ├── css │ │ ├── avalanche.css │ │ └── main.css │ ├── img │ │ ├── chevrol-bel-air.png │ │ └── react.png │ ├── index.html │ └── js │ │ └── .gitkeep ├── readme.md ├── src │ ├── app.js │ └── components │ │ ├── regions.js │ │ ├── wine-app.js │ │ ├── wine-list.js │ │ └── wine.js ├── tests │ ├── bootstrap.js │ ├── components │ │ ├── regions.spec.js │ │ ├── wine-app.spec.js │ │ ├── wine-list.spec.js │ │ └── wine.spec.js │ └── index.js ├── webpack.config.js ├── wines-components.png └── wines.png ├── step-3-done ├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── package.json ├── public │ ├── css │ │ ├── avalanche.css │ │ └── main.css │ ├── img │ │ ├── chevrol-bel-air.png │ │ └── react.png │ ├── index.html │ └── js │ │ └── .gitkeep ├── readme.md ├── src │ ├── app.js │ ├── components │ │ ├── not-found.js │ │ ├── regions.js │ │ ├── wine-app.js │ │ ├── wine-list.js │ │ └── wine.js │ └── index.js ├── tests │ ├── bootstrap.js │ ├── components │ │ ├── regions.spec.js │ │ ├── wine-app.spec.js │ │ ├── wine-list.spec.js │ │ └── wine.spec.js │ └── index.js └── webpack.config.js ├── step-3 ├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── package.json ├── public │ ├── css │ │ ├── avalanche.css │ │ └── main.css │ ├── img │ │ ├── chevrol-bel-air.png │ │ └── react.png │ ├── index.html │ └── js │ │ └── .gitkeep ├── readme.md ├── src │ ├── app.js │ ├── components │ │ ├── not-found.js │ │ ├── regions.js │ │ ├── wine-app.js │ │ ├── wine-list.js │ │ └── wine.js │ └── index.js ├── tests │ ├── bootstrap.js │ ├── components │ │ ├── regions.spec.js │ │ ├── wine-app.spec.js │ │ ├── wine-list.spec.js │ │ └── wine.spec.js │ └── index.js ├── view1.png ├── view2.png ├── view3.png └── webpack.config.js ├── step-4-done ├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── package.json ├── public │ ├── css │ │ ├── avalanche.css │ │ └── main.css │ ├── img │ │ ├── chevrol-bel-air.png │ │ └── react.png │ ├── index.html │ └── js │ │ └── .gitkeep ├── readme.md ├── src │ ├── app.js │ ├── components │ │ ├── comments.js │ │ ├── not-found.js │ │ ├── regions.js │ │ ├── wine-app.js │ │ ├── wine-list.js │ │ └── wine.js │ └── index.js ├── tests │ ├── bootstrap.js │ ├── components │ │ ├── regions.spec.js │ │ ├── wine-app.spec.js │ │ ├── wine-list.spec.js │ │ └── wine.spec.js │ └── index.js └── webpack.config.js ├── step-4 ├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── mockup.png ├── package.json ├── public │ ├── css │ │ ├── avalanche.css │ │ └── main.css │ ├── img │ │ ├── chevrol-bel-air.png │ │ └── react.png │ ├── index.html │ └── js │ │ └── .gitkeep ├── readme.md ├── src │ ├── app.js │ ├── components │ │ ├── comments.js │ │ ├── not-found.js │ │ ├── regions.js │ │ ├── wine-app.js │ │ ├── wine-list.js │ │ └── wine.js │ └── index.js ├── tests │ ├── bootstrap.js │ ├── components │ │ ├── regions.spec.js │ │ ├── wine-app.spec.js │ │ ├── wine-list.spec.js │ │ └── wine.spec.js │ └── index.js └── webpack.config.js ├── step-5-done ├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── package.json ├── public │ ├── css │ │ ├── avalanche.css │ │ └── main.css │ ├── img │ │ ├── chevrol-bel-air.png │ │ └── react.png │ ├── index.html │ └── js │ │ └── .gitkeep ├── readme.md ├── src │ ├── actions │ │ └── index.js │ ├── app.js │ ├── components │ │ ├── comments.js │ │ ├── not-found.js │ │ ├── regions.js │ │ ├── stats.js │ │ ├── wine-app.js │ │ ├── wine-list.js │ │ └── wine.js │ ├── index.js │ └── reducers │ │ ├── comments.js │ │ ├── index.js │ │ └── likes.js ├── tests │ ├── bootstrap.js │ ├── components │ │ ├── regions.spec.js │ │ ├── wine-app.spec.js │ │ ├── wine-list.spec.js │ │ └── wine.spec.js │ └── index.js └── webpack.config.js ├── step-5 ├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── package.json ├── public │ ├── css │ │ ├── avalanche.css │ │ └── main.css │ ├── img │ │ ├── chevrol-bel-air.png │ │ └── react.png │ ├── index.html │ └── js │ │ └── .gitkeep ├── readme.md ├── src │ ├── actions │ │ └── index.js │ ├── app.js │ ├── components │ │ ├── clicker.js │ │ ├── comments.js │ │ ├── not-found.js │ │ ├── regions.js │ │ ├── wine-app.js │ │ ├── wine-list.js │ │ └── wine.js │ ├── index.js │ └── reducers │ │ ├── counter.js │ │ └── index.js ├── tests │ ├── bootstrap.js │ ├── components │ │ ├── regions.spec.js │ │ ├── wine-app.spec.js │ │ ├── wine-list.spec.js │ │ └── wine.spec.js │ └── index.js ├── view1.png └── webpack.config.js ├── step-6-done ├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── package.json ├── public │ ├── css │ │ ├── avalanche.css │ │ └── main.css │ ├── img │ │ ├── chevrol-bel-air.png │ │ └── react.png │ ├── index.html │ └── js │ │ └── .gitkeep ├── readme.md ├── src │ ├── actions │ │ └── index.js │ ├── app.js │ ├── components │ │ ├── comments.js │ │ ├── devtools.js │ │ ├── not-found.js │ │ ├── regions.js │ │ ├── stats.js │ │ ├── wine-app.js │ │ ├── wine-list.js │ │ └── wine.js │ ├── index.js │ └── reducers │ │ ├── comments.js │ │ ├── http.js │ │ ├── index.js │ │ ├── likes.js │ │ ├── regions.js │ │ ├── title.js │ │ └── wines.js ├── tests │ ├── bootstrap.js │ ├── components │ │ ├── regions.spec.js │ │ ├── wine-app.spec.js │ │ ├── wine-list.spec.js │ │ └── wine.spec.js │ └── index.js └── webpack.config.js ├── step-6 ├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── package.json ├── public │ ├── css │ │ ├── avalanche.css │ │ └── main.css │ ├── img │ │ ├── chevrol-bel-air.png │ │ └── react.png │ ├── index.html │ └── js │ │ └── .gitkeep ├── readme.md ├── src │ ├── actions │ │ └── index.js │ ├── app.js │ ├── components │ │ ├── comments.js │ │ ├── devtools.js │ │ ├── not-found.js │ │ ├── regions.js │ │ ├── stats.js │ │ ├── wine-app.js │ │ ├── wine-list.js │ │ └── wine.js │ ├── index.js │ └── reducers │ │ ├── comments.js │ │ ├── http.js │ │ ├── index.js │ │ └── likes.js ├── tests │ ├── bootstrap.js │ ├── components │ │ ├── regions.spec.js │ │ ├── wine-app.spec.js │ │ ├── wine-list.spec.js │ │ └── wine.spec.js │ └── index.js └── webpack.config.js ├── step-7 ├── .babelrc ├── .eslintignore ├── .eslintrc ├── .gitignore ├── package.json ├── public │ ├── css │ │ ├── avalanche.css │ │ └── main.css │ ├── img │ │ ├── chevrol-bel-air.png │ │ └── react.png │ ├── index.html │ └── js │ │ └── .gitkeep ├── readme.md ├── src │ ├── actions │ │ └── index.js │ ├── app.js │ ├── components │ │ ├── comments.js │ │ ├── devtools.js │ │ ├── not-found.js │ │ ├── regions.js │ │ ├── stats.js │ │ ├── wine-app.js │ │ ├── wine-list.js │ │ └── wine.js │ ├── index.js │ └── reducers │ │ ├── comments.js │ │ ├── http.js │ │ ├── index.js │ │ ├── likes.js │ │ ├── regions.js │ │ ├── title.js │ │ └── wines.js ├── tests │ ├── bootstrap.js │ ├── components │ │ ├── regions.spec.js │ │ ├── wine-app.spec.js │ │ ├── wine-list.spec.js │ │ └── wine.spec.js │ └── index.js └── webpack.config.js ├── step-8-done ├── .eslintignore ├── .eslintrc ├── .flowconfig ├── .gitignore ├── .watchmanconfig ├── android │ ├── app │ │ ├── app.iml │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ ├── react.gradle │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── wines │ │ │ │ └── MainActivity.java │ │ │ └── res │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ └── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── wines.iml ├── index.android.js ├── index.ios.js ├── ios │ ├── wines.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── wines.xcscheme │ ├── wines │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Base.lproj │ │ │ └── LaunchScreen.xib │ │ ├── Images.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── Info.plist │ │ └── main.m │ └── winesTests │ │ ├── Info.plist │ │ └── winesTests.m ├── package.json └── src │ ├── actions │ └── index.js │ ├── app.js │ ├── components │ ├── button.js │ ├── comments.js │ ├── liked.png │ ├── loading.android.js │ ├── loading.ios.js │ ├── not-found.android.js │ ├── region-cell.js │ ├── regions.js │ ├── style.js │ ├── unliked.png │ ├── wine-app.android.js │ ├── wine-app.ios.js │ ├── wine-cell.js │ ├── wine-list.js │ └── wine.js │ └── reducers │ ├── comments.js │ ├── http.js │ ├── index.js │ ├── likes.js │ ├── regions.js │ ├── title.js │ └── wines.js ├── step-8 ├── .eslintignore ├── .eslintrc ├── .flowconfig ├── .gitignore ├── .watchmanconfig ├── android │ ├── app │ │ ├── app.iml │ │ ├── build.gradle │ │ ├── proguard-rules.pro │ │ ├── react.gradle │ │ └── src │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── wines │ │ │ │ └── MainActivity.java │ │ │ └── res │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ └── values │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle │ └── wines.iml ├── index.android.js ├── index.ios.js ├── ios │ ├── wines.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── wines.xcscheme │ ├── wines │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Base.lproj │ │ │ └── LaunchScreen.xib │ │ ├── Images.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── Info.plist │ │ └── main.m │ └── winesTests │ │ ├── Info.plist │ │ └── winesTests.m ├── live-reload.png ├── package.json ├── reactnative-emulator.png ├── readme.md ├── regions-android.png ├── regions-ios.png ├── src │ ├── actions │ │ └── index.js │ ├── app.js │ ├── components │ │ ├── button.js │ │ ├── comments.js │ │ ├── liked.png │ │ ├── loading.android.js │ │ ├── loading.ios.js │ │ ├── region-cell.js │ │ ├── regions.js │ │ ├── style.js │ │ ├── unliked.png │ │ ├── wine-app.android.js │ │ ├── wine-app.ios.js │ │ ├── wine-cell.js │ │ ├── wine-list.js │ │ └── wine.js │ └── reducers │ │ ├── comments.js │ │ ├── http.js │ │ ├── index.js │ │ ├── likes.js │ │ ├── regions.js │ │ ├── title.js │ │ └── wines.js ├── wine-liked-android.png ├── wine-liked-ios.png ├── wine-unliked-android.png ├── wine-unliked-ios.png ├── wines-android.png └── wines-ios.png ├── test-all-done.sh └── test-all-undone.sh /.gitignore: -------------------------------------------------------------------------------- 1 | /step-live 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /api/.gitignore: -------------------------------------------------------------------------------- 1 | # Node.js 2 | node_modules 3 | npm-debug.log 4 | -------------------------------------------------------------------------------- /api/apidoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-workshop-api-doc", 3 | "version": "1.0.0", 4 | "description": "React Workshop API documentation", 5 | "title": "React Workshop API", 6 | "url" : "http://localhost:3000/api" 7 | } 8 | -------------------------------------------------------------------------------- /api/doc/api_project.js: -------------------------------------------------------------------------------- 1 | define({ "name": "react-workshop-api-doc", "version": "1.0.0", "description": "React Workshop API documentation", "title": "React Workshop API", "url": "http://localhost:3000/api", "sampleUrl": false, "apidoc": "0.2.0", "generator": { "name": "apidoc", "time": "2016-04-11T08:48:33.421Z", "url": "http://apidocjs.com", "version": "0.15.1" } }); 2 | -------------------------------------------------------------------------------- /api/doc/api_project.json: -------------------------------------------------------------------------------- 1 | { "name": "react-workshop-api-doc", "version": "1.0.0", "description": "React Workshop API documentation", "title": "React Workshop API", "url": "http://localhost:3000/api", "sampleUrl": false, "apidoc": "0.2.0", "generator": { "name": "apidoc", "time": "2016-04-11T08:48:33.421Z", "url": "http://apidocjs.com", "version": "0.15.1" } } 2 | -------------------------------------------------------------------------------- /api/doc/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/doc/img/favicon.ico -------------------------------------------------------------------------------- /api/doc/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/doc/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /api/doc/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/doc/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /api/doc/locales/zh.js: -------------------------------------------------------------------------------- 1 | define({ 2 | zh: { 3 | 'Allowed values​​:' : '允許值:', 4 | 'Compare all with predecessor': '預先比較所有', 5 | 'compare changes to:' : '比較變更:', 6 | 'compared to' : '對比', 7 | 'Default value:' : '默認值:', 8 | 'Description' : '描述', 9 | 'Field' : '字段', 10 | 'General' : '概括', 11 | 'Generated with' : '生成工具', 12 | 'Name' : '名稱', 13 | 'No response values​​.' : '無對應資料.', 14 | 'optional' : '選項', 15 | 'Parameter' : '參數', 16 | 'Permission:' : '允許:', 17 | 'Response' : '回應', 18 | 'Send' : '發送', 19 | 'Send a Sample Request' : '發送試用需求', 20 | 'show up to version:' : '顯示到版本:', 21 | 'Size range:' : '尺寸範圍:', 22 | 'Type' : '類型', 23 | 'url' : '網址' 24 | } 25 | }); 26 | -------------------------------------------------------------------------------- /api/doc/locales/zh_cn.js: -------------------------------------------------------------------------------- 1 | define({ 2 | 'zh_cn': { 3 | 'Allowed values:' : '允许值:', 4 | 'Compare all with predecessor': '与所有较早的比较', 5 | 'compare changes to:' : '将当前版本与指定版本比较:', 6 | 'compared to' : '相比于', 7 | 'Default value:' : '默认值:', 8 | 'Description' : '描述', 9 | 'Field' : '字段', 10 | 'General' : '概要', 11 | 'Generated with' : '基于', 12 | 'Name' : '名称', 13 | 'No response values.' : '无返回值.', 14 | 'optional' : '可选', 15 | 'Parameter' : '参数', 16 | 'Permission:' : '权限:', 17 | 'Response' : '返回', 18 | 'Send' : '发送', 19 | 'Send a Sample Request' : '发送示例请求', 20 | 'show up to version:' : '显示到指定版本:', 21 | 'Size range:' : '取值范围:', 22 | 'Type' : '类型', 23 | 'url' : '网址' 24 | } 25 | }); 26 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-apollo.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["com",/^#[^\n\r]*/,null,"#"],["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,null,'"']],[["kwd",/^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\s/, 2 | null],["typ",/^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[ES]?BANK=?|BLOCK|BNKSUM|E?CADR|COUNT\*?|2?DEC\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\s/,null],["lit",/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[!-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["apollo","agc","aea"]); 3 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-basic.js: -------------------------------------------------------------------------------- 1 | var a=null; 2 | PR.registerLangHandler(PR.createSimpleLexer([["str",/^"(?:[^\n\r"\\]|\\.)*(?:"|$)/,a,'"'],["pln",/^\s+/,a," \r\n\t\u00a0"]],[["com",/^REM[^\n\r]*/,a],["kwd",/^\b(?:AND|CLOSE|CLR|CMD|CONT|DATA|DEF ?FN|DIM|END|FOR|GET|GOSUB|GOTO|IF|INPUT|LET|LIST|LOAD|NEW|NEXT|NOT|ON|OPEN|OR|POKE|PRINT|READ|RESTORE|RETURN|RUN|SAVE|STEP|STOP|SYS|THEN|TO|VERIFY|WAIT)\b/,a],["pln",/^[a-z][^\W_]?(?:\$|%)?/i,a],["lit",/^(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?/i,a,"0123456789"],["pun", 3 | /^.[^\s\w"$%.]*/,a]]),["basic","cbm"]); 4 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-css.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n\u000c"]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]+)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//], 2 | ["com",/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}\b/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); 3 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-dart.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"]],[["com",/^#!.*/],["kwd",/^\b(?:import|library|part of|part|as|show|hide)\b/i],["com",/^\/\/.*/],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["kwd",/^\b(?:class|interface)\b/i],["kwd",/^\b(?:assert|break|case|catch|continue|default|do|else|finally|for|if|in|is|new|return|super|switch|this|throw|try|while)\b/i],["kwd",/^\b(?:abstract|const|extends|factory|final|get|implements|native|operator|set|static|typedef|var)\b/i], 2 | ["typ",/^\b(?:bool|double|dynamic|int|num|object|string|void)\b/i],["kwd",/^\b(?:false|null|true)\b/i],["str",/^r?'''[\S\s]*?[^\\]'''/],["str",/^r?"""[\S\s]*?[^\\]"""/],["str",/^r?'('|[^\n\f\r]*?[^\\]')/],["str",/^r?"("|[^\n\f\r]*?[^\\]")/],["pln",/^[$_a-z]\w*/i],["pun",/^[!%&*+/:<-?^|~-]/],["lit",/^\b0x[\da-f]+/i],["lit",/^\b\d+(?:\.\d*)?(?:e[+-]?\d+)?/i],["lit",/^\b\.\d+(?:e[+-]?\d+)?/i],["pun",/^[(),.;[\]{}]/]]), 3 | ["dart"]); 4 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-erlang.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t-\r ]+/,null,"\t\n\u000b\u000c\r "],["str",/^"(?:[^\n\f\r"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["lit",/^[a-z]\w*/],["lit",/^'(?:[^\n\f\r'\\]|\\[^&])+'?/,null,"'"],["lit",/^\?[^\t\n ({]+/,null,"?"],["lit",/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)/i,null,"0123456789"]],[["com",/^%[^\n]*/],["kwd",/^(?:module|attributes|do|let|in|letrec|apply|call|primop|case|of|end|when|fun|try|catch|receive|after|char|integer|float,atom,string,var)\b/], 2 | ["kwd",/^-[_a-z]+/],["typ",/^[A-Z_]\w*/],["pun",/^[,.;]/]]),["erlang","erl"]); 3 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-go.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["pln",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])+(?:'|$)|`[^`]*(?:`|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\/\*[\S\s]*?\*\/)/],["pln",/^(?:[^"'/`]|\/(?![*/]))+/]]),["go"]); 2 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-hs.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t-\r ]+/,null,"\t\n\u000b\u000c\r "],["str",/^"(?:[^\n\f\r"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["str",/^'(?:[^\n\f\r'\\]|\\[^&])'?/,null,"'"],["lit",/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)/i,null,"0123456789"]],[["com",/^(?:--+[^\n\f\r]*|{-(?:[^-]|-+[^}-])*-})/],["kwd",/^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^\d'A-Za-z]|$)/, 2 | null],["pln",/^(?:[A-Z][\w']*\.)*[A-Za-z][\w']*/],["pun",/^[^\d\t-\r "'A-Za-z]+/]]),["hs"]); 3 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-lisp.js: -------------------------------------------------------------------------------- 1 | var a=null; 2 | PR.registerLangHandler(PR.createSimpleLexer([["opn",/^\(+/,a,"("],["clo",/^\)+/,a,")"],["com",/^;[^\n\r]*/,a,";"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \u00a0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/,a], 3 | ["lit",/^[+-]?(?:[#0]x[\da-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[de][+-]?\d+)?)/i],["lit",/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[_a-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/i],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["cl","el","lisp","lsp","scm","ss","rkt"]); 4 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-llvm.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^!?"(?:[^"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["com",/^;[^\n\r]*/,null,";"]],[["pln",/^[!%@](?:[$\-.A-Z_a-z][\w$\-.]*|\d+)/],["kwd",/^[^\W\d]\w*/,null],["lit",/^\d+\.\d+/],["lit",/^(?:\d+|0[Xx][\dA-Fa-f]+)/],["pun",/^[(-*,:<->[\]{}]|\.\.\.$/]]),["llvm","ll"]); 2 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-lua.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$))/,null,"\"'"]],[["com",/^--(?:\[(=*)\[[\S\s]*?(?:]\1]|$)|[^\n\r]*)/],["str",/^\[(=*)\[[\S\s]*?(?:]\1]|$)/],["kwd",/^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,null],["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i], 2 | ["pln",/^[_a-z]\w*/i],["pun",/^[^\w\t\n\r \xa0][^\w\t\n\r "'+=\xa0-]*/]]),["lua"]); 3 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-ml.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["com",/^#(?:if[\t\n\r \xa0]+(?:[$_a-z][\w']*|``[^\t\n\r`]*(?:``|$))|else|endif|light)/i,null,"#"],["str",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])(?:'|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\(\*[\S\s]*?\*\))/],["kwd",/^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\b/], 2 | ["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],["pln",/^(?:[_a-z][\w']*[!#?]?|``[^\t\n\r`]*(?:``|$))/i],["pun",/^[^\w\t\n\r "'\xa0]+/]]),["fs","ml"]); 3 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-mumps.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^"(?:[^"]|\\.)*"/,null,'"']],[["com",/^;[^\n\r]*/,null,";"],["dec",/^\$(?:d|device|ec|ecode|es|estack|et|etrap|h|horolog|i|io|j|job|k|key|p|principal|q|quit|st|stack|s|storage|sy|system|t|test|tl|tlevel|tr|trestart|x|y|z[a-z]*|a|ascii|c|char|d|data|e|extract|f|find|fn|fnumber|g|get|j|justify|l|length|na|name|o|order|p|piece|ql|qlength|qs|qsubscript|q|query|r|random|re|reverse|s|select|st|stack|t|text|tr|translate|nan)\b/i, 2 | null],["kwd",/^(?:[^$]b|break|c|close|d|do|e|else|f|for|g|goto|h|halt|h|hang|i|if|j|job|k|kill|l|lock|m|merge|n|new|o|open|q|quit|r|read|s|set|tc|tcommit|tre|trestart|tro|trollback|ts|tstart|u|use|v|view|w|write|x|xecute)\b/i,null],["lit",/^[+-]?(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?/i],["pln",/^[a-z][^\W_]*/i],["pun",/^[^\w\t\n\r"$%;^\xa0]|_/]]),["mumps"]); 3 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-pascal.js: -------------------------------------------------------------------------------- 1 | var a=null; 2 | PR.registerLangHandler(PR.createSimpleLexer([["str",/^'(?:[^\n\r'\\]|\\.)*(?:'|$)/,a,"'"],["pln",/^\s+/,a," \r\n\t\u00a0"]],[["com",/^\(\*[\S\s]*?(?:\*\)|$)|^{[\S\s]*?(?:}|$)/,a],["kwd",/^(?:absolute|and|array|asm|assembler|begin|case|const|constructor|destructor|div|do|downto|else|end|external|for|forward|function|goto|if|implementation|in|inline|interface|interrupt|label|mod|not|object|of|or|packed|procedure|program|record|repeat|set|shl|shr|then|to|type|unit|until|uses|var|virtual|while|with|xor)\b/i,a], 3 | ["lit",/^(?:true|false|self|nil)/i,a],["pln",/^[a-z][^\W_]*/i,a],["lit",/^(?:\$[\da-f]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?)/i,a,"0123456789"],["pun",/^.[^\s\w$'./@]*/,a]]),["pascal"]); 4 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-proto.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.sourceDecorator({keywords:"bytes,default,double,enum,extend,extensions,false,group,import,max,message,option,optional,package,repeated,required,returns,rpc,service,syntax,to,true",types:/^(bool|(double|s?fixed|[su]?int)(32|64)|float|string)\b/,cStyleComments:!0}),["proto"]); 2 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-r.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["str",/^'(?:[^'\\]|\\[\S\s])*(?:'|$)/,null,"'"]],[["com",/^#.*/],["kwd",/^(?:if|else|for|while|repeat|in|next|break|return|switch|function)(?![\w.])/],["lit",/^0[Xx][\dA-Fa-f]+([Pp]\d+)?[Li]?/],["lit",/^[+-]?(\d+(\.\d+)?|\.\d+)([Ee][+-]?\d+)?[Li]?/],["lit",/^(?:NULL|NA(?:_(?:integer|real|complex|character)_)?|Inf|TRUE|FALSE|NaN|\.\.(?:\.|\d+))(?![\w.])/], 2 | ["pun",/^(?:<>?|-|==|<=|>=|<|>|&&?|!=|\|\|?|[!*+/^]|%.*?%|[$=@~]|:{1,3}|[(),;?[\]{}])/],["pln",/^(?:[A-Za-z]+[\w.]*|\.[^\W\d][\w.]*)(?![\w.])/],["str",/^`.+`/]]),["r","s","R","S","Splus"]); 3 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-rd.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["com",/^%[^\n\r]*/,null,"%"]],[["lit",/^\\(?:cr|l?dots|R|tab)\b/],["kwd",/^\\[@-Za-z]+/],["kwd",/^#(?:ifn?def|endif)/],["pln",/^\\[{}]/],["pun",/^[()[\]{}]+/]]),["Rd","rd"]); 2 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-scala.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["str",/^"(?:""(?:""?(?!")|[^"\\]|\\.)*"{0,3}|(?:[^\n\r"\\]|\\.)*"?)/,null,'"'],["lit",/^`(?:[^\n\r\\`]|\\.)*`?/,null,"`"],["pun",/^[!#%&(--:-@[-^{-~]+/,null,"!#%&()*+,-:;<=>?@[\\]^{|}~"]],[["str",/^'(?:[^\n\r'\\]|\\(?:'|[^\n\r']+))'/],["lit",/^'[$A-Z_a-z][\w$]*(?![\w$'])/],["kwd",/^(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|object|override|package|private|protected|requires|return|sealed|super|throw|trait|try|type|val|var|while|with|yield)\b/], 2 | ["lit",/^(?:true|false|null|this)\b/],["lit",/^(?:0(?:[0-7]+|x[\da-f]+)l?|(?:0|[1-9]\d*)(?:(?:\.\d+)?(?:e[+-]?\d+)?f?|l?)|\\.\d+(?:e[+-]?\d+)?f?)/i],["typ",/^[$_]*[A-Z][\d$A-Z_]*[a-z][\w$]*/],["pln",/^[$A-Z_a-z][\w$]*/],["com",/^\/(?:\/.*|\*(?:\/|\**[^*/])*(?:\*+\/?)?)/],["pun",/^(?:\.+|\/)/]]),["scala"]); 3 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-tcl.js: -------------------------------------------------------------------------------- 1 | var a=null; 2 | PR.registerLangHandler(PR.createSimpleLexer([["opn",/^{+/,a,"{"],["clo",/^}+/,a,"}"],["com",/^#[^\n\r]*/,a,"#"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \u00a0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:after|append|apply|array|break|case|catch|continue|error|eval|exec|exit|expr|for|foreach|if|incr|info|proc|return|set|switch|trace|uplevel|upvar|while)\b/,a],["lit",/^[+-]?(?:[#0]x[\da-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[de][+-]?\d+)?)/i],["lit", 3 | /^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[_a-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/i],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["tcl"]); 4 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-tex.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r \u00a0"],["com",/^%[^\n\r]*/,null,"%"]],[["kwd",/^\\[@-Za-z]+/],["kwd",/^\\./],["typ",/^[$&]/],["lit",/[+-]?(?:\.\d+|\d+(?:\.\d*)?)(cm|em|ex|in|pc|pt|bp|mm)/i],["pun",/^[()=[\]{}]+/]]),["latex","tex"]); 2 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-wiki.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\d\t a-gi-z\xa0]+/,null,"\t \u00a0abcdefgijklmnopqrstuvwxyz0123456789"],["pun",/^[*=[\]^~]+/,null,"=*~^[]"]],[["lang-wiki.meta",/(?:^^|\r\n?|\n)(#[a-z]+)\b/],["lit",/^[A-Z][a-z][\da-z]+[A-Z][a-z][^\W_]+\b/],["lang-",/^{{{([\S\s]+?)}}}/],["lang-",/^`([^\n\r`]+)`/],["str",/^https?:\/\/[^\s#/?]*(?:\/[^\s#?]*)?(?:\?[^\s#]*)?(?:#\S*)?/i],["pln",/^(?:\r\n|[\S\s])[^\n\r#*=A-[^`h{~]*/]]),["wiki"]); 2 | PR.registerLangHandler(PR.createSimpleLexer([["kwd",/^#[a-z]+/i,null,"#"]],[]),["wiki.meta"]); 3 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/lang-yaml.js: -------------------------------------------------------------------------------- 1 | var a=null; 2 | PR.registerLangHandler(PR.createSimpleLexer([["pun",/^[:>?|]+/,a,":|>?"],["dec",/^%(?:YAML|TAG)[^\n\r#]+/,a,"%"],["typ",/^&\S+/,a,"&"],["typ",/^!\S*/,a,"!"],["str",/^"(?:[^"\\]|\\.)*(?:"|$)/,a,'"'],["str",/^'(?:[^']|'')*(?:'|$)/,a,"'"],["com",/^#[^\n\r]*/,a,"#"],["pln",/^\s+/,a," \t\r\n"]],[["dec",/^(?:---|\.\.\.)(?:[\n\r]|$)/],["pun",/^-/],["kwd",/^\w+:[\n\r ]/],["pln",/^\w+/]]),["yaml","yml"]); 3 | -------------------------------------------------------------------------------- /api/doc/vendor/prettify/prettify.css: -------------------------------------------------------------------------------- 1 | .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} -------------------------------------------------------------------------------- /api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-workshop-api", 3 | "description": "React Workshop API", 4 | "version": "0.0.0", 5 | "dependencies": { 6 | "express": "4.13.4", 7 | "body-parser": "1.15.0" 8 | }, 9 | "devDependencies": { 10 | "apidoc": "0.15.1" 11 | }, 12 | "scripts" : { 13 | "start": "node src/server.js", 14 | "doc": "apidoc -i src/ -o doc/" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /api/src/data/images/aligote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/aligote.png -------------------------------------------------------------------------------- /api/src/data/images/arcins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/arcins.png -------------------------------------------------------------------------------- /api/src/data/images/bel-air.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/bel-air.png -------------------------------------------------------------------------------- /api/src/data/images/boisson.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/boisson.png -------------------------------------------------------------------------------- /api/src/data/images/bollinger-special-cuvee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/bollinger-special-cuvee.png -------------------------------------------------------------------------------- /api/src/data/images/bonnamy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/bonnamy.png -------------------------------------------------------------------------------- /api/src/data/images/chantalouette.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/chantalouette.png -------------------------------------------------------------------------------- /api/src/data/images/charme-cos-labory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/charme-cos-labory.png -------------------------------------------------------------------------------- /api/src/data/images/cheval-noir.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/cheval-noir.png -------------------------------------------------------------------------------- /api/src/data/images/chevrol-bel-air.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/chevrol-bel-air.png -------------------------------------------------------------------------------- /api/src/data/images/clarendelle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/clarendelle.png -------------------------------------------------------------------------------- /api/src/data/images/cormeil-figeac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/cormeil-figeac.png -------------------------------------------------------------------------------- /api/src/data/images/cote-beaune-village.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/cote-beaune-village.png -------------------------------------------------------------------------------- /api/src/data/images/deutz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/deutz.png -------------------------------------------------------------------------------- /api/src/data/images/domaine-chatenoy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/domaine-chatenoy.png -------------------------------------------------------------------------------- /api/src/data/images/domaine-desoucherie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/domaine-desoucherie.png -------------------------------------------------------------------------------- /api/src/data/images/domaine-petit-coteau.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/domaine-petit-coteau.png -------------------------------------------------------------------------------- /api/src/data/images/fleur-haut-bages-liberal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/fleur-haut-bages-liberal.png -------------------------------------------------------------------------------- /api/src/data/images/jaillance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/jaillance.png -------------------------------------------------------------------------------- /api/src/data/images/la-noe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/la-noe.png -------------------------------------------------------------------------------- /api/src/data/images/la-roche.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/la-roche.png -------------------------------------------------------------------------------- /api/src/data/images/lacaussade-saint-martin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/lacaussade-saint-martin.png -------------------------------------------------------------------------------- /api/src/data/images/ladoix-pierre-andre.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/ladoix-pierre-andre.png -------------------------------------------------------------------------------- /api/src/data/images/laniote.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/laniote.png -------------------------------------------------------------------------------- /api/src/data/images/lanson-blanc-de-blanc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/lanson-blanc-de-blanc.png -------------------------------------------------------------------------------- /api/src/data/images/lanson.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/lanson.png -------------------------------------------------------------------------------- /api/src/data/images/latour-camblanes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/latour-camblanes.png -------------------------------------------------------------------------------- /api/src/data/images/laurent-perrier.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/laurent-perrier.png -------------------------------------------------------------------------------- /api/src/data/images/les-cailloux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/les-cailloux.png -------------------------------------------------------------------------------- /api/src/data/images/les-champs-clos-blanc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/les-champs-clos-blanc.png -------------------------------------------------------------------------------- /api/src/data/images/les-champs-clos-rouge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/les-champs-clos-rouge.png -------------------------------------------------------------------------------- /api/src/data/images/les-hauts-de-tour-prignac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/les-hauts-de-tour-prignac.png -------------------------------------------------------------------------------- /api/src/data/images/les-vaillons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/les-vaillons.png -------------------------------------------------------------------------------- /api/src/data/images/lestage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/lestage.png -------------------------------------------------------------------------------- /api/src/data/images/macon-lugny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/macon-lugny.png -------------------------------------------------------------------------------- /api/src/data/images/marsannay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/marsannay.png -------------------------------------------------------------------------------- /api/src/data/images/moet-chandon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/moet-chandon.png -------------------------------------------------------------------------------- /api/src/data/images/mouton-cadet-rose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/mouton-cadet-rose.png -------------------------------------------------------------------------------- /api/src/data/images/mouton-cadet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/mouton-cadet.png -------------------------------------------------------------------------------- /api/src/data/images/oratoire-chasse-spleen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/oratoire-chasse-spleen.png -------------------------------------------------------------------------------- /api/src/data/images/patache-d-aux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/patache-d-aux.png -------------------------------------------------------------------------------- /api/src/data/images/philippe-de-valois.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/philippe-de-valois.png -------------------------------------------------------------------------------- /api/src/data/images/pol-roger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/pol-roger.png -------------------------------------------------------------------------------- /api/src/data/images/rahoul.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/rahoul.png -------------------------------------------------------------------------------- /api/src/data/images/reserve-des-vignerons-blanc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/reserve-des-vignerons-blanc.png -------------------------------------------------------------------------------- /api/src/data/images/reserve-des-vignerons-rouge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/reserve-des-vignerons-rouge.png -------------------------------------------------------------------------------- /api/src/data/images/roc-de-boissac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/roc-de-boissac.png -------------------------------------------------------------------------------- /api/src/data/images/teynac.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/teynac.png -------------------------------------------------------------------------------- /api/src/data/images/thomas-barton-reserve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/thomas-barton-reserve.png -------------------------------------------------------------------------------- /api/src/data/images/tour-des-termes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/tour-des-termes.png -------------------------------------------------------------------------------- /api/src/data/images/vin-de-messe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/api/src/data/images/vin-de-messe.png -------------------------------------------------------------------------------- /dependencies/.gitignore: -------------------------------------------------------------------------------- 1 | *.zip 2 | node_modules 3 | -------------------------------------------------------------------------------- /dependencies/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-workshop-dependencies", 3 | "version": "1.0.0", 4 | "description": "Just a project to fetch all npm dependencies", 5 | "dependencies": { 6 | "express": "4.13.4", 7 | "body-parser": "1.15.0", 8 | "react": "0.14.7", 9 | "react-dom": "0.14.7", 10 | "whatwg-fetch": "0.11.0", 11 | "react-router": "2.0.1", 12 | "react-redux": "4.4.1", 13 | "redux": "3.3.1", 14 | "react-router-redux": "4.0.0", 15 | "redux-thunk": "2.0.1" 16 | }, 17 | "devDependencies": { 18 | "apidoc": "0.15.1", 19 | "babel-loader": "6.2.4", 20 | "babel-preset-es2015": "6.6.0", 21 | "babel-preset-react": "6.5.0", 22 | "babel-register": "6.7.2", 23 | "chai": "3.5.0", 24 | "eslint": "2.4.0", 25 | "eslint-plugin-react": "4.2.3", 26 | "jsdom": "8.1.0", 27 | "mocha": "2.4.5", 28 | "react-addons-test-utils": "0.14.7", 29 | "redux-devtools": "3.1.1", 30 | "redux-devtools-dock-monitor": "1.1.0", 31 | "redux-devtools-log-monitor": "1.0.5", 32 | "webpack": "1.12.14", 33 | "webpack-dev-server": "1.14.1", 34 | "enzyme": "2.2.0", 35 | "sinon": "1.17.3" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | APP_PATH=`pwd` 4 | 5 | STEPS=`find $APP_PATH -type d -name "step-*"` 6 | 7 | for item in ${STEPS} 8 | do 9 | if [ -f "$item/package.json" ]; 10 | then 11 | cd "$item" 12 | echo "fetching dependencies for $item" 13 | npm install 14 | else 15 | echo "nothing to do for $item" 16 | fi 17 | done 18 | 19 | cd "$APP_PATH/api" 20 | echo "fetching dependencies for the Wine API" 21 | npm install 22 | 23 | cd "$APP_PATH" 24 | -------------------------------------------------------------------------------- /print/pdf/all.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/print/pdf/all.pdf -------------------------------------------------------------------------------- /print/pdf/index.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/print/pdf/index.pdf -------------------------------------------------------------------------------- /print/pdf/step-0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/print/pdf/step-0.pdf -------------------------------------------------------------------------------- /print/pdf/step-1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/print/pdf/step-1.pdf -------------------------------------------------------------------------------- /print/pdf/step-2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/print/pdf/step-2.pdf -------------------------------------------------------------------------------- /print/pdf/step-3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/print/pdf/step-3.pdf -------------------------------------------------------------------------------- /print/pdf/step-4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/print/pdf/step-4.pdf -------------------------------------------------------------------------------- /print/pdf/step-5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/print/pdf/step-5.pdf -------------------------------------------------------------------------------- /print/pdf/step-6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/print/pdf/step-6.pdf -------------------------------------------------------------------------------- /print/pdf/step-7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/print/pdf/step-7.pdf -------------------------------------------------------------------------------- /print/pdf/step-8.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/print/pdf/step-8.pdf -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # React Workshop 2 | 3 | Le workshop a été déplacé [dans l'organisation react-bootcamp](https://github.com/react-bootcamp/react-workshop) 4 | -------------------------------------------------------------------------------- /step-0-done/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /step-0-done/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | webpack.config.js 3 | public 4 | README.md 5 | -------------------------------------------------------------------------------- /step-0-done/.gitignore: -------------------------------------------------------------------------------- 1 | # Node.js 2 | node_modules 3 | npm-debug.log 4 | 5 | # Bundles 6 | bundle.js 7 | bundle.js.map 8 | -------------------------------------------------------------------------------- /step-0-done/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-workshop", 3 | "description": "React Workshop", 4 | "version": "0.1.0", 5 | "dependencies": { 6 | "react": "0.14.7", 7 | "react-dom": "0.14.7" 8 | }, 9 | "devDependencies": { 10 | "babel-loader": "6.2.4", 11 | "babel-preset-es2015": "6.6.0", 12 | "babel-preset-react": "6.5.0", 13 | "babel-register": "6.7.2", 14 | "eslint": "2.4.0", 15 | "eslint-plugin-react": "4.2.3", 16 | "webpack": "1.12.14", 17 | "webpack-dev-server": "1.14.1" 18 | }, 19 | "scripts": { 20 | "lint": "eslint src", 21 | "bundle": "webpack -p --colors --progress", 22 | "start": "webpack-dev-server -d --colors --inline --content-base public", 23 | "build": "npm run lint && npm run bundle" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /step-0-done/public/css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Roboto', sans-serif; 3 | } 4 | -------------------------------------------------------------------------------- /step-0-done/public/img/chevrol-bel-air.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-0-done/public/img/chevrol-bel-air.png -------------------------------------------------------------------------------- /step-0-done/public/img/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-0-done/public/img/react.png -------------------------------------------------------------------------------- /step-0-done/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Workshop 6 | 7 | 8 | 9 | 10 | 11 |

Wines

12 | 13 |
14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /step-0-done/public/js/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-0-done/public/js/.gitkeep -------------------------------------------------------------------------------- /step-0-done/readme.md: -------------------------------------------------------------------------------- 1 | # Etape 0 2 | 3 | Ce dossier contient la version finale de [l'étape 0]('../step-0') 4 | -------------------------------------------------------------------------------- /step-0-done/src/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | import Wine from './components/wine'; 5 | 6 | ReactDOM.render( 7 | , 8 | document.getElementById('main') 9 | ); 10 | -------------------------------------------------------------------------------- /step-0-done/src/components/wine.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const WineStyle = { 4 | padding: 8, 5 | boxShadow: '0 1px 6px rgba(0,0,0,0.12), 0 1px 4px rgba(0,0,0,0.12)' 6 | }; 7 | 8 | const Wine = React.createClass({ 9 | propTypes: { 10 | name: React.PropTypes.string 11 | }, 12 | 13 | render() { 14 | return ( 15 |
16 | {this.props.name} 17 |
18 | ); 19 | } 20 | }); 21 | 22 | export default Wine; 23 | -------------------------------------------------------------------------------- /step-0-done/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | 3 | module.exports = { 4 | output: { 5 | path: './public/js/', 6 | publicPath: '/js/', 7 | filename: 'bundle.js' 8 | }, 9 | entry: { 10 | app: ['./src/app.js'] 11 | }, 12 | resolve: { 13 | extensions: ['', '.js', '.jsx'] 14 | }, 15 | module: { 16 | loaders: [ 17 | { 18 | test: /\.js$/, 19 | exclude: /node_modules/, 20 | loader: 'babel' 21 | } 22 | ] 23 | }, 24 | devServer: { 25 | historyApiFallback: true, 26 | proxy: { 27 | '/api/*': { 28 | target: 'http://localhost:3000' 29 | } 30 | } 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /step-1-done/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /step-1-done/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | webpack.config.js 3 | public 4 | README.md 5 | -------------------------------------------------------------------------------- /step-1-done/.gitignore: -------------------------------------------------------------------------------- 1 | # Node.js 2 | node_modules 3 | npm-debug.log 4 | 5 | # Bundles 6 | bundle.js 7 | bundle.js.map 8 | -------------------------------------------------------------------------------- /step-1-done/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-workshop", 3 | "description": "React Workshop", 4 | "version": "0.1.0", 5 | "dependencies": { 6 | "react": "0.14.7", 7 | "react-dom": "0.14.7" 8 | }, 9 | "devDependencies": { 10 | "babel-loader": "6.2.4", 11 | "babel-preset-es2015": "6.6.0", 12 | "babel-preset-react": "6.5.0", 13 | "babel-register": "6.7.2", 14 | "chai": "3.5.0", 15 | "eslint": "2.4.0", 16 | "eslint-plugin-react": "4.2.3", 17 | "jsdom": "8.1.0", 18 | "mocha": "2.4.5", 19 | "react-addons-test-utils": "0.14.7", 20 | "webpack": "1.12.14", 21 | "webpack-dev-server": "1.14.1" 22 | }, 23 | "scripts": { 24 | "lint": "eslint src tests", 25 | "test": "mocha --compilers js:babel-register tests/index.js", 26 | "bundle": "webpack -p --colors --progress", 27 | "start": "webpack-dev-server -d --colors --inline --content-base public", 28 | "build": "npm run test && npm run lint && npm run bundle" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /step-1-done/public/css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Roboto', sans-serif; 3 | } 4 | -------------------------------------------------------------------------------- /step-1-done/public/img/chevrol-bel-air.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-1-done/public/img/chevrol-bel-air.png -------------------------------------------------------------------------------- /step-1-done/public/img/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-1-done/public/img/react.png -------------------------------------------------------------------------------- /step-1-done/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Workshop 6 | 7 | 8 | 9 | 10 | 11 |

Wines

12 | 13 |
14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /step-1-done/public/js/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-1-done/public/js/.gitkeep -------------------------------------------------------------------------------- /step-1-done/readme.md: -------------------------------------------------------------------------------- 1 | # Etape 1 2 | 3 | Ce dossier contient la version finale de [l'étape 1]('../step-1') 4 | -------------------------------------------------------------------------------- /step-1-done/src/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | import Wine from './components/wine'; 5 | 6 | ReactDOM.render( 7 | , 8 | document.getElementById('main') 9 | ); 10 | -------------------------------------------------------------------------------- /step-1-done/src/components/wine.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const WineStyle = { 4 | padding: 8, 5 | boxShadow: '0 1px 6px rgba(0,0,0,0.12), 0 1px 4px rgba(0,0,0,0.12)' 6 | }; 7 | 8 | const Wine = React.createClass({ 9 | propTypes: { 10 | name: React.PropTypes.string 11 | }, 12 | 13 | render() { 14 | return ( 15 |
16 | {this.props.name} 17 |
18 | ); 19 | } 20 | }); 21 | 22 | export default Wine; 23 | -------------------------------------------------------------------------------- /step-1-done/tests/bootstrap.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: 0 */ 2 | 3 | import jsdom from 'jsdom'; 4 | 5 | export function bootstrapEnv(body = '') { 6 | const doc = jsdom.jsdom(`${body}`); 7 | const win = doc.defaultView; 8 | function propagateToGlobal(window) { 9 | for (const key in window) { 10 | if (!window.hasOwnProperty(key)) continue; 11 | if (key in global) continue; 12 | global[key] = window[key]; 13 | } 14 | } 15 | global.document = doc; 16 | global.window = win; 17 | propagateToGlobal(win); 18 | console.log('\nENV setup is done !!!'); 19 | } 20 | -------------------------------------------------------------------------------- /step-1-done/tests/components/wine.spec.js: -------------------------------------------------------------------------------- 1 | /* eslint no-undef:0 */ 2 | 3 | import React from 'react'; 4 | import { expect } from 'chai'; 5 | import ReactTestUtils from 'react-addons-test-utils'; 6 | 7 | import Wine from '../../src/components/wine'; 8 | 9 | describe('Wine', () => { 10 | it('affiche le nom du vin', () => { 11 | const wine = ReactTestUtils.renderIntoDocument(); 12 | const div = ReactTestUtils.findRenderedDOMComponentWithTag(wine, 'div'); 13 | expect(div.textContent).to.be.equal('Un bon Bourgogne'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /step-1-done/tests/index.js: -------------------------------------------------------------------------------- 1 | /* eslint no-unused-vars:0, no-console: 0 */ 2 | 3 | import { bootstrapEnv } from './bootstrap'; 4 | 5 | bootstrapEnv(); 6 | 7 | console.log('===================================================================\n'); 8 | console.log('If you want to run other tests, don\'t forget ton include them in the "tests" array.'); 9 | console.log('of $ROOT/tests/index.js)'); 10 | console.log('\n===================================================================\n'); 11 | 12 | const tests = [ 13 | require('./components/wine.spec.js') 14 | ]; 15 | -------------------------------------------------------------------------------- /step-1-done/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | 3 | module.exports = { 4 | output: { 5 | path: './public/js/', 6 | publicPath: '/js/', 7 | filename: 'bundle.js' 8 | }, 9 | entry: { 10 | app: ['./src/app.js'] 11 | }, 12 | resolve: { 13 | extensions: ['', '.js', '.jsx'] 14 | }, 15 | module: { 16 | loaders: [ 17 | { 18 | test: /\.js$/, 19 | exclude: /node_modules/, 20 | loader: 'babel' 21 | } 22 | ] 23 | }, 24 | devServer: { 25 | historyApiFallback: true, 26 | proxy: { 27 | '/api/*': { 28 | target: 'http://localhost:3000' 29 | } 30 | } 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /step-1/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /step-1/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | webpack.config.js 3 | public 4 | README.md 5 | -------------------------------------------------------------------------------- /step-1/.gitignore: -------------------------------------------------------------------------------- 1 | # Node.js 2 | node_modules 3 | npm-debug.log 4 | 5 | # Bundles 6 | bundle.js 7 | bundle.js.map 8 | -------------------------------------------------------------------------------- /step-1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-workshop", 3 | "description": "React Workshop", 4 | "version": "0.1.0", 5 | "dependencies": { 6 | "react": "0.14.7", 7 | "react-dom": "0.14.7" 8 | }, 9 | "devDependencies": { 10 | "babel-loader": "6.2.4", 11 | "babel-preset-es2015": "6.6.0", 12 | "babel-preset-react": "6.5.0", 13 | "babel-register": "6.7.2", 14 | "chai": "3.5.0", 15 | "eslint": "2.4.0", 16 | "eslint-plugin-react": "4.2.3", 17 | "jsdom": "8.1.0", 18 | "mocha": "2.4.5", 19 | "react-addons-test-utils": "0.14.7", 20 | "webpack": "1.12.14", 21 | "webpack-dev-server": "1.14.1" 22 | }, 23 | "scripts": { 24 | "lint": "eslint src tests", 25 | "test": "mocha --compilers js:babel-register tests/index.js", 26 | "bundle": "webpack -p --colors --progress", 27 | "start": "webpack-dev-server -d --colors --inline --content-base public", 28 | "build": "npm run test && npm run lint && npm run bundle" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /step-1/public/css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Roboto', sans-serif; 3 | } 4 | -------------------------------------------------------------------------------- /step-1/public/img/chevrol-bel-air.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-1/public/img/chevrol-bel-air.png -------------------------------------------------------------------------------- /step-1/public/img/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-1/public/img/react.png -------------------------------------------------------------------------------- /step-1/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Workshop 6 | 7 | 8 | 9 | 10 | 11 |

Wines

12 | 13 |
14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /step-1/public/js/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-1/public/js/.gitkeep -------------------------------------------------------------------------------- /step-1/src/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | import Wine from './components/wine'; 5 | 6 | ReactDOM.render( 7 | , 8 | document.getElementById('main') 9 | ); 10 | -------------------------------------------------------------------------------- /step-1/src/components/wine.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const WineStyle = { 4 | padding: 8, 5 | boxShadow: '0 1px 6px rgba(0,0,0,0.12), 0 1px 4px rgba(0,0,0,0.12)' 6 | }; 7 | 8 | const Wine = React.createClass({ 9 | propTypes: { 10 | name: React.PropTypes.string 11 | }, 12 | 13 | render() { 14 | return ( 15 |
16 | {this.props.name} 17 |
18 | ); 19 | } 20 | }); 21 | 22 | export default Wine; 23 | -------------------------------------------------------------------------------- /step-1/tests/bootstrap.js: -------------------------------------------------------------------------------- 1 | import jsdom from 'jsdom'; 2 | 3 | export function bootstrapEnv(body = '') { 4 | const doc = jsdom.jsdom(`${body}`); 5 | const win = doc.defaultView; 6 | function propagateToGlobal(window) { 7 | for (const key in window) { 8 | if (!window.hasOwnProperty(key)) continue; 9 | if (key in global) continue; 10 | global[key] = window[key]; 11 | } 12 | } 13 | global.document = doc; 14 | global.window = win; 15 | propagateToGlobal(win); 16 | console.log('\nENV setup is done !!!'); 17 | } 18 | -------------------------------------------------------------------------------- /step-1/tests/index.js: -------------------------------------------------------------------------------- 1 | import { bootstrapEnv } from './bootstrap'; 2 | 3 | bootstrapEnv(); 4 | 5 | const tests = [ 6 | // TODO : add you tests here !!! 7 | ]; 8 | -------------------------------------------------------------------------------- /step-1/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | 3 | module.exports = { 4 | output: { 5 | path: './public/js/', 6 | publicPath: '/js/', 7 | filename: 'bundle.js' 8 | }, 9 | entry: { 10 | app: ['./src/app.js'] 11 | }, 12 | resolve: { 13 | extensions: ['', '.js', '.jsx'] 14 | }, 15 | module: { 16 | loaders: [ 17 | { 18 | test: /\.js$/, 19 | exclude: /node_modules/, 20 | loader: 'babel' 21 | } 22 | ] 23 | }, 24 | devServer: { 25 | historyApiFallback: true, 26 | proxy: { 27 | '/api/*': { 28 | target: 'http://localhost:3000' 29 | } 30 | } 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /step-2-done/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /step-2-done/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | webpack.config.js 3 | public 4 | README.md 5 | -------------------------------------------------------------------------------- /step-2-done/.gitignore: -------------------------------------------------------------------------------- 1 | # Node.js 2 | node_modules 3 | npm-debug.log 4 | 5 | # Bundles 6 | bundle.js 7 | bundle.js.map 8 | -------------------------------------------------------------------------------- /step-2-done/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-workshop", 3 | "description": "React Workshop", 4 | "version": "0.1.0", 5 | "dependencies": { 6 | "react": "0.14.7", 7 | "react-dom": "0.14.7", 8 | "whatwg-fetch": "0.11.0" 9 | }, 10 | "devDependencies": { 11 | "babel-loader": "6.2.4", 12 | "babel-preset-es2015": "6.6.0", 13 | "babel-preset-react": "6.5.0", 14 | "babel-register": "6.7.2", 15 | "chai": "3.5.0", 16 | "enzyme": "2.2.0", 17 | "eslint": "2.4.0", 18 | "eslint-plugin-react": "4.2.3", 19 | "jsdom": "8.1.0", 20 | "mocha": "2.4.5", 21 | "react-addons-test-utils": "0.14.7", 22 | "sinon": "1.17.3", 23 | "webpack": "1.12.14", 24 | "webpack-dev-server": "1.14.1" 25 | }, 26 | "scripts": { 27 | "lint": "eslint src", 28 | "test": "mocha --compilers js:babel-register tests/index.js", 29 | "bundle": "webpack -p --colors --progress", 30 | "start": "webpack-dev-server -d --colors --inline --content-base public", 31 | "build": "npm run lint && npm run bundle" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /step-2-done/public/css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Roboto', sans-serif; 3 | } 4 | -------------------------------------------------------------------------------- /step-2-done/public/img/chevrol-bel-air.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-2-done/public/img/chevrol-bel-air.png -------------------------------------------------------------------------------- /step-2-done/public/img/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-2-done/public/img/react.png -------------------------------------------------------------------------------- /step-2-done/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Workshop 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Wines

13 | 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /step-2-done/public/js/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-2-done/public/js/.gitkeep -------------------------------------------------------------------------------- /step-2-done/readme.md: -------------------------------------------------------------------------------- 1 | # Etape 2 2 | 3 | Ce dossier contient la version finale de [l'étape 2]('../step-2') 4 | -------------------------------------------------------------------------------- /step-2-done/src/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | import WineApp from './components/wine-app'; 5 | 6 | ReactDOM.render( 7 | , 8 | document.getElementById('main') 9 | ); 10 | -------------------------------------------------------------------------------- /step-2-done/src/components/regions.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | 3 | const computeRegionStyle = function(region, selected) { 4 | let style = { 5 | padding: 16 6 | }; 7 | if (region === selected) { 8 | style['fontWeight'] = 'bold'; 9 | style['backgroundColor'] = 'lightGrey'; 10 | } 11 | return style; 12 | } 13 | 14 | const Regions = React.createClass({ 15 | propTypes: { 16 | onRegionChange: PropTypes.func, 17 | regions: PropTypes.arrayOf(PropTypes.string), 18 | selected: PropTypes.string 19 | }, 20 | 21 | handleRegionClick(event) { 22 | this.props.onRegionChange(event.target.textContent); 23 | }, 24 | 25 | render () { 26 | return ( 27 |
28 | { 29 | this.props.regions.map(region => 30 |
34 | {region} 35 |
36 | ) 37 | } 38 |
39 | ) 40 | } 41 | }) 42 | 43 | export default Regions 44 | -------------------------------------------------------------------------------- /step-2-done/tests/bootstrap.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: 0 */ 2 | 3 | import jsdom from 'jsdom'; 4 | 5 | export function bootstrapEnv(body = '') { 6 | const doc = jsdom.jsdom(`${body}`); 7 | const win = doc.defaultView; 8 | function propagateToGlobal(window) { 9 | for (const key in window) { 10 | if (!window.hasOwnProperty(key)) continue; 11 | if (key in global) continue; 12 | global[key] = window[key]; 13 | } 14 | } 15 | global.document = doc; 16 | global.window = win; 17 | propagateToGlobal(win); 18 | // console.log('\nENV setup is done !!!'); 19 | } 20 | -------------------------------------------------------------------------------- /step-2-done/tests/index.js: -------------------------------------------------------------------------------- 1 | /* eslint no-unused-vars:0, no-console: 0 */ 2 | 3 | import { bootstrapEnv } from './bootstrap'; 4 | 5 | bootstrapEnv(); 6 | 7 | require('./components/regions.spec.js') 8 | require('./components/wine-list.spec.js') 9 | require('./components/wine.spec.js') 10 | require('./components/wine-app.spec.js') 11 | -------------------------------------------------------------------------------- /step-2-done/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | 3 | module.exports = { 4 | output: { 5 | path: './public/js/', 6 | publicPath: '/js/', 7 | filename: 'bundle.js' 8 | }, 9 | entry: { 10 | app: ['./src/app.js'] 11 | }, 12 | resolve: { 13 | extensions: ['', '.js', '.jsx'] 14 | }, 15 | module: { 16 | loaders: [ 17 | { 18 | test: /\.js$/, 19 | exclude: /node_modules/, 20 | loader: 'babel' 21 | } 22 | ] 23 | }, 24 | devServer: { 25 | historyApiFallback: true, 26 | proxy: { 27 | '/api/*': { 28 | target: 'http://localhost:3000' 29 | } 30 | } 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /step-2/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /step-2/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | webpack.config.js 3 | public 4 | README.md 5 | -------------------------------------------------------------------------------- /step-2/.gitignore: -------------------------------------------------------------------------------- 1 | # Node.js 2 | node_modules 3 | npm-debug.log 4 | 5 | # Bundles 6 | bundle.js 7 | bundle.js.map 8 | -------------------------------------------------------------------------------- /step-2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-workshop", 3 | "description": "React Workshop", 4 | "version": "0.1.0", 5 | "dependencies": { 6 | "react": "0.14.7", 7 | "react-dom": "0.14.7", 8 | "whatwg-fetch": "0.11.0" 9 | }, 10 | "devDependencies": { 11 | "babel-loader": "6.2.4", 12 | "babel-preset-es2015": "6.6.0", 13 | "babel-preset-react": "6.5.0", 14 | "babel-register": "6.7.2", 15 | "chai": "3.5.0", 16 | "eslint": "2.4.0", 17 | "eslint-plugin-react": "4.2.3", 18 | "enzyme": "2.2.0", 19 | "jsdom": "8.1.0", 20 | "mocha": "2.4.5", 21 | "react-addons-test-utils": "0.14.7", 22 | "sinon": "1.17.3", 23 | "webpack": "1.12.14", 24 | "webpack-dev-server": "1.14.1" 25 | }, 26 | "scripts": { 27 | "lint": "eslint src", 28 | "test": "mocha --compilers js:babel-register tests/index.js", 29 | "bundle": "webpack -p --colors --progress", 30 | "start": "webpack-dev-server -d --colors --inline --content-base public", 31 | "build": "npm run lint && npm run bundle" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /step-2/public/css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Roboto', sans-serif; 3 | } 4 | -------------------------------------------------------------------------------- /step-2/public/img/chevrol-bel-air.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-2/public/img/chevrol-bel-air.png -------------------------------------------------------------------------------- /step-2/public/img/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-2/public/img/react.png -------------------------------------------------------------------------------- /step-2/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Workshop 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Wines

13 | 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /step-2/public/js/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-2/public/js/.gitkeep -------------------------------------------------------------------------------- /step-2/src/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | import WineApp from './components/wine-app'; 5 | 6 | ReactDOM.render( 7 | , 8 | document.getElementById('main') 9 | ); 10 | -------------------------------------------------------------------------------- /step-2/src/components/regions.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; // eslint-disable-line 2 | 3 | // vous devriez utiliser cette fonction pour le style de chaque région 4 | function computeRegionStyle(region, selected) { // eslint-disable-line 5 | let style = { 6 | padding: 16 7 | }; 8 | if (region === selected) { 9 | style['fontWeight'] = 'bold'; 10 | style['backgroundColor'] = 'lightGrey'; 11 | } 12 | return style; 13 | } 14 | 15 | const Regions = React.createClass({ 16 | render () { 17 | return ( 18 |
19 |

TODO : Regions

20 |
21 | ) 22 | } 23 | }) 24 | 25 | export default Regions 26 | -------------------------------------------------------------------------------- /step-2/src/components/wine-app.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; // eslint-disable-line 2 | 3 | const WineApp = React.createClass({ 4 | render () { 5 | return ( 6 |
7 |
8 |

Regions

9 | ... 10 |
11 |
12 |

Wine List

13 | ... 14 |
15 |
16 |

Wine Description

17 | ... 18 |
19 |
20 | ) 21 | } 22 | }) 23 | 24 | export default WineApp 25 | -------------------------------------------------------------------------------- /step-2/src/components/wine-list.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; // eslint-disable-line 2 | 3 | // vous devriez utiliser cette fonction pour le style de chaque région 4 | function computeWineStyle(region, selected) { // eslint-disable-line 5 | let style = { 6 | padding: 16 7 | }; 8 | if (region === selected) { 9 | style['fontWeight'] = 'bold'; 10 | style['backgroundColor'] = 'lightGrey'; 11 | } 12 | return style; 13 | } 14 | 15 | const WineList = React.createClass({ 16 | render () { 17 | return ( 18 |
19 |

TODO : WineList

20 |
21 | ) 22 | } 23 | }) 24 | 25 | export default WineList 26 | -------------------------------------------------------------------------------- /step-2/src/components/wine.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const WineStyle = { 4 | padding: 8, 5 | boxShadow: '0 1px 6px rgba(0,0,0,0.12), 0 1px 4px rgba(0,0,0,0.12)' 6 | }; 7 | 8 | const Styles = { // eslint-disable-line 9 | Card: { 10 | padding: 8, 11 | boxSizing: 'border-box', 12 | boxShadow: '0 1px 6px rgba(0,0,0,0.12), 0 1px 4px rgba(0,0,0,0.12)', 13 | minHeight: 280 14 | }, 15 | Title: { 16 | fontWeight: 'bold', 17 | fontSize: '1.2em' 18 | }, 19 | Info: { 20 | marginTop: 16, 21 | marginBottom: 16 22 | }, 23 | Label: { 24 | color: 'white', 25 | marginRight: 8, 26 | padding: 4, 27 | background: 'grey', 28 | borderRadius: '4px' 29 | }, 30 | Image: { 31 | float: 'left' 32 | } 33 | }; 34 | 35 | const Wine = React.createClass({ 36 | propTypes: { 37 | name: React.PropTypes.string 38 | }, 39 | 40 | render() { 41 | return ( 42 |
43 | {this.props.name} 44 |
45 | ); 46 | } 47 | }); 48 | 49 | export default Wine; 50 | -------------------------------------------------------------------------------- /step-2/tests/bootstrap.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: 0 */ 2 | 3 | import jsdom from 'jsdom'; 4 | 5 | export function bootstrapEnv(body = '') { 6 | const doc = jsdom.jsdom(`${body}`); 7 | const win = doc.defaultView; 8 | function propagateToGlobal(window) { 9 | for (const key in window) { 10 | if (!window.hasOwnProperty(key)) continue; 11 | if (key in global) continue; 12 | global[key] = window[key]; 13 | } 14 | } 15 | global.document = doc; 16 | global.window = win; 17 | propagateToGlobal(win); 18 | // console.log('\nENV setup is done !!!'); 19 | } 20 | -------------------------------------------------------------------------------- /step-2/tests/index.js: -------------------------------------------------------------------------------- 1 | /* eslint no-unused-vars:0, no-console: 0 */ 2 | 3 | import { bootstrapEnv } from './bootstrap'; 4 | 5 | bootstrapEnv(); 6 | 7 | require('./components/regions.spec.js') 8 | require('./components/wine-list.spec.js') 9 | require('./components/wine.spec.js') 10 | require('./components/wine-app.spec.js') 11 | -------------------------------------------------------------------------------- /step-2/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | 3 | module.exports = { 4 | output: { 5 | path: './public/js/', 6 | publicPath: '/js/', 7 | filename: 'bundle.js' 8 | }, 9 | entry: { 10 | app: ['./src/app.js'] 11 | }, 12 | resolve: { 13 | extensions: ['', '.js', '.jsx'] 14 | }, 15 | module: { 16 | loaders: [ 17 | { 18 | test: /\.js$/, 19 | exclude: /node_modules/, 20 | loader: 'babel' 21 | } 22 | ] 23 | }, 24 | devServer: { 25 | historyApiFallback: true, 26 | proxy: { 27 | '/api/*': { 28 | target: 'http://localhost:3000' 29 | } 30 | } 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /step-2/wines-components.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-2/wines-components.png -------------------------------------------------------------------------------- /step-2/wines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-2/wines.png -------------------------------------------------------------------------------- /step-3-done/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /step-3-done/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | webpack.config.js 3 | public 4 | README.md 5 | -------------------------------------------------------------------------------- /step-3-done/.gitignore: -------------------------------------------------------------------------------- 1 | # Node.js 2 | node_modules 3 | npm-debug.log 4 | 5 | # Bundles 6 | bundle.js 7 | bundle.js.map 8 | -------------------------------------------------------------------------------- /step-3-done/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-workshop", 3 | "description": "React Workshop", 4 | "version": "0.1.0", 5 | "dependencies": { 6 | "react": "0.14.7", 7 | "react-dom": "0.14.7", 8 | "react-router": "2.0.1", 9 | "whatwg-fetch": "0.11.0" 10 | }, 11 | "devDependencies": { 12 | "babel-loader": "6.2.4", 13 | "babel-preset-es2015": "6.6.0", 14 | "babel-preset-react": "6.5.0", 15 | "babel-register": "6.7.2", 16 | "chai": "3.5.0", 17 | "enzyme": "2.2.0", 18 | "eslint": "2.4.0", 19 | "eslint-plugin-react": "4.2.3", 20 | "jsdom": "8.1.0", 21 | "mocha": "2.4.5", 22 | "react-addons-test-utils": "0.14.7", 23 | "sinon": "1.17.3", 24 | "webpack": "1.12.14", 25 | "webpack-dev-server": "1.14.1" 26 | }, 27 | "scripts": { 28 | "lint": "eslint src", 29 | "test": "mocha --compilers js:babel-register tests/index.js", 30 | "bundle": "webpack -p --colors --progress", 31 | "start": "webpack-dev-server -d --colors --inline --content-base public", 32 | "build": "npm run lint && npm run bundle" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /step-3-done/public/css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Roboto', sans-serif; 3 | } 4 | -------------------------------------------------------------------------------- /step-3-done/public/img/chevrol-bel-air.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-3-done/public/img/chevrol-bel-air.png -------------------------------------------------------------------------------- /step-3-done/public/img/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-3-done/public/img/react.png -------------------------------------------------------------------------------- /step-3-done/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Workshop 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Wines

13 | 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /step-3-done/public/js/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-3-done/public/js/.gitkeep -------------------------------------------------------------------------------- /step-3-done/readme.md: -------------------------------------------------------------------------------- 1 | # Etape 3 2 | 3 | Ce dossier contient la version finale de [l'étape 3]('../step-3') 4 | -------------------------------------------------------------------------------- /step-3-done/src/app.js: -------------------------------------------------------------------------------- 1 | /* eslint react/jsx-max-props-per-line: 0 */ 2 | 3 | import 'whatwg-fetch'; 4 | 5 | import React, { PropTypes } from 'react'; 6 | 7 | import WineApp from './components/wine-app'; 8 | import { RegionsPage } from './components/regions'; 9 | import { WineListPage } from './components/wine-list'; 10 | import { WinePage } from './components/wine'; 11 | import { NotFound } from './components/not-found'; 12 | 13 | import { Router, Route, browserHistory, IndexRoute } from 'react-router'; 14 | 15 | export const App = React.createClass({ 16 | propTypes: { 17 | history: PropTypes.object, // eslint-disable-line 18 | }, 19 | render() { 20 | const history = this.props.history || browserHistory; 21 | return ( 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | ); 31 | } 32 | }); 33 | -------------------------------------------------------------------------------- /step-3-done/src/components/not-found.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const NotFound = React.createClass({ 4 | render() { 5 | return ( 6 |

Il semble que vous n'êtes pas au bon endroit !!!

7 | ); 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /step-3-done/src/components/wine-app.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | 3 | const WineApp = React.createClass({ 4 | 5 | propTypes: { 6 | children: PropTypes.element 7 | }, 8 | 9 | contextTypes: { 10 | router: React.PropTypes.object 11 | }, 12 | 13 | getInitialState() { 14 | return { 15 | title: '' 16 | }; 17 | }, 18 | 19 | setTitle(title) { 20 | this.setState({ title }); 21 | }, 22 | 23 | goBack() { 24 | this.context.router.goBack(); 25 | }, 26 | 27 | render () { 28 | return ( 29 |
30 |
31 |

{this.state.title}

32 | {this.props.children && React.cloneElement(this.props.children, { 33 | setTitle: this.setTitle 34 | })} 35 |
36 |
37 | ); 38 | } 39 | }) 40 | 41 | export default WineApp 42 | -------------------------------------------------------------------------------- /step-3-done/src/index.js: -------------------------------------------------------------------------------- 1 | import 'whatwg-fetch'; 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | import { App } from './app'; 7 | 8 | ReactDOM.render(, document.getElementById('main')); 9 | -------------------------------------------------------------------------------- /step-3-done/tests/bootstrap.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: 0 */ 2 | 3 | import jsdom from 'jsdom'; 4 | 5 | export function bootstrapEnv(body = '') { 6 | const doc = jsdom.jsdom(`${body}`); 7 | const win = doc.defaultView; 8 | function propagateToGlobal(window) { 9 | for (const key in window) { 10 | if (!window.hasOwnProperty(key)) continue; 11 | if (key in global) continue; 12 | global[key] = window[key]; 13 | } 14 | } 15 | global.document = doc; 16 | global.window = win; 17 | propagateToGlobal(win); 18 | // console.log('\nENV setup is done !!!'); 19 | } 20 | -------------------------------------------------------------------------------- /step-3-done/tests/index.js: -------------------------------------------------------------------------------- 1 | /* eslint no-unused-vars:0, no-console: 0 */ 2 | 3 | import { bootstrapEnv } from './bootstrap'; 4 | 5 | bootstrapEnv(); 6 | 7 | require('./components/regions.spec.js') 8 | require('./components/wine-list.spec.js') 9 | require('./components/wine.spec.js') 10 | require('./components/wine-app.spec.js') 11 | -------------------------------------------------------------------------------- /step-3-done/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | 3 | module.exports = { 4 | output: { 5 | path: './public/js/', 6 | publicPath: '/js/', 7 | filename: 'bundle.js' 8 | }, 9 | entry: { 10 | app: ['./src/index.js'] 11 | }, 12 | resolve: { 13 | extensions: ['', '.js', '.jsx'] 14 | }, 15 | module: { 16 | loaders: [ 17 | { 18 | test: /\.js$/, 19 | exclude: /node_modules/, 20 | loader: 'babel' 21 | } 22 | ] 23 | }, 24 | devServer: { 25 | historyApiFallback: true, 26 | proxy: { 27 | '/api/*': { 28 | target: 'http://localhost:3000' 29 | } 30 | } 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /step-3/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /step-3/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | webpack.config.js 3 | public 4 | README.md 5 | -------------------------------------------------------------------------------- /step-3/.gitignore: -------------------------------------------------------------------------------- 1 | # Node.js 2 | node_modules 3 | npm-debug.log 4 | 5 | # Bundles 6 | bundle.js 7 | bundle.js.map 8 | -------------------------------------------------------------------------------- /step-3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-workshop", 3 | "description": "React Workshop", 4 | "version": "0.1.0", 5 | "dependencies": { 6 | "react": "0.14.7", 7 | "react-dom": "0.14.7", 8 | "react-router": "2.0.1", 9 | "whatwg-fetch": "0.11.0" 10 | }, 11 | "devDependencies": { 12 | "babel-loader": "6.2.4", 13 | "babel-preset-es2015": "6.6.0", 14 | "babel-preset-react": "6.5.0", 15 | "babel-register": "6.7.2", 16 | "chai": "3.5.0", 17 | "enzyme": "2.2.0", 18 | "eslint": "2.4.0", 19 | "eslint-plugin-react": "4.2.3", 20 | "jsdom": "8.1.0", 21 | "mocha": "2.4.5", 22 | "react-addons-test-utils": "0.14.7", 23 | "sinon": "1.17.3", 24 | "webpack": "1.12.14", 25 | "webpack-dev-server": "1.14.1" 26 | }, 27 | "scripts": { 28 | "lint": "eslint src", 29 | "test": "mocha --compilers js:babel-register tests/index.js", 30 | "bundle": "webpack -p --colors --progress", 31 | "start": "webpack-dev-server -d --colors --inline --content-base public", 32 | "build": "npm run lint && npm run bundle" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /step-3/public/css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Roboto', sans-serif; 3 | } 4 | -------------------------------------------------------------------------------- /step-3/public/img/chevrol-bel-air.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-3/public/img/chevrol-bel-air.png -------------------------------------------------------------------------------- /step-3/public/img/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-3/public/img/react.png -------------------------------------------------------------------------------- /step-3/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Workshop 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Wines

13 | 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /step-3/public/js/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-3/public/js/.gitkeep -------------------------------------------------------------------------------- /step-3/src/app.js: -------------------------------------------------------------------------------- 1 | /* eslint react/jsx-max-props-per-line: 0 */ 2 | 3 | import 'whatwg-fetch'; 4 | 5 | import React, { PropTypes } from 'react'; 6 | 7 | import WineApp from './components/wine-app'; 8 | import { RegionsPage } from './components/regions'; 9 | import { WineListPage } from './components/wine-list'; 10 | import { WinePage } from './components/wine'; 11 | import { NotFound } from './components/not-found'; 12 | 13 | import { Router, Route, browserHistory, IndexRoute } from 'react-router'; 14 | 15 | export const App = React.createClass({ 16 | propTypes: { 17 | history: PropTypes.object, // eslint-disable-line 18 | }, 19 | render() { 20 | const history = this.props.history || browserHistory; 21 | return ( 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | ); 31 | } 32 | }); 33 | -------------------------------------------------------------------------------- /step-3/src/components/not-found.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const NotFound = React.createClass({ 4 | render() { 5 | return ( 6 |

TODO : NotFound

7 | ); 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /step-3/src/components/wine-app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | const WineApp = React.createClass({ 4 | render () { 5 | return ( 6 |
7 |
8 | {this.props.children} 9 |
10 |
11 | ); 12 | } 13 | }) 14 | 15 | export default WineApp 16 | -------------------------------------------------------------------------------- /step-3/src/index.js: -------------------------------------------------------------------------------- 1 | import 'whatwg-fetch'; 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | import { App } from './app'; 7 | 8 | ReactDOM.render(, document.getElementById('main')); 9 | -------------------------------------------------------------------------------- /step-3/tests/bootstrap.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: 0 */ 2 | 3 | import jsdom from 'jsdom'; 4 | 5 | export function bootstrapEnv(body = '') { 6 | const doc = jsdom.jsdom(`${body}`); 7 | const win = doc.defaultView; 8 | function propagateToGlobal(window) { 9 | for (const key in window) { 10 | if (!window.hasOwnProperty(key)) continue; 11 | if (key in global) continue; 12 | global[key] = window[key]; 13 | } 14 | } 15 | global.document = doc; 16 | global.window = win; 17 | propagateToGlobal(win); 18 | // console.log('\nENV setup is done !!!'); 19 | } 20 | -------------------------------------------------------------------------------- /step-3/tests/index.js: -------------------------------------------------------------------------------- 1 | /* eslint no-unused-vars:0, no-console: 0 */ 2 | 3 | import { bootstrapEnv } from './bootstrap'; 4 | 5 | bootstrapEnv(); 6 | 7 | require('./components/regions.spec.js') 8 | require('./components/wine-list.spec.js') 9 | require('./components/wine.spec.js') 10 | require('./components/wine-app.spec.js') 11 | -------------------------------------------------------------------------------- /step-3/view1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-3/view1.png -------------------------------------------------------------------------------- /step-3/view2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-3/view2.png -------------------------------------------------------------------------------- /step-3/view3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-3/view3.png -------------------------------------------------------------------------------- /step-3/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | 3 | module.exports = { 4 | output: { 5 | path: './public/js/', 6 | publicPath: '/js/', 7 | filename: 'bundle.js' 8 | }, 9 | entry: { 10 | app: ['./src/index.js'] 11 | }, 12 | resolve: { 13 | extensions: ['', '.js', '.jsx'] 14 | }, 15 | module: { 16 | loaders: [ 17 | { 18 | test: /\.js$/, 19 | exclude: /node_modules/, 20 | loader: 'babel' 21 | } 22 | ] 23 | }, 24 | devServer: { 25 | historyApiFallback: true, 26 | proxy: { 27 | '/api/*': { 28 | target: 'http://localhost:3000' 29 | } 30 | } 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /step-4-done/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /step-4-done/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | webpack.config.js 3 | public 4 | README.md 5 | -------------------------------------------------------------------------------- /step-4-done/.gitignore: -------------------------------------------------------------------------------- 1 | # Node.js 2 | node_modules 3 | npm-debug.log 4 | 5 | # Bundles 6 | bundle.js 7 | bundle.js.map 8 | -------------------------------------------------------------------------------- /step-4-done/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-workshop", 3 | "description": "React Workshop", 4 | "version": "0.1.0", 5 | "dependencies": { 6 | "react": "0.14.7", 7 | "react-dom": "0.14.7", 8 | "react-router": "2.0.1", 9 | "whatwg-fetch": "0.11.0" 10 | }, 11 | "devDependencies": { 12 | "babel-loader": "6.2.4", 13 | "babel-preset-es2015": "6.6.0", 14 | "babel-preset-react": "6.5.0", 15 | "babel-register": "6.7.2", 16 | "chai": "3.5.0", 17 | "enzyme": "2.2.0", 18 | "eslint": "2.4.0", 19 | "eslint-plugin-react": "4.2.3", 20 | "jsdom": "8.1.0", 21 | "mocha": "2.4.5", 22 | "react-addons-test-utils": "0.14.7", 23 | "sinon": "1.17.3", 24 | "webpack": "1.12.14", 25 | "webpack-dev-server": "1.14.1" 26 | }, 27 | "scripts": { 28 | "lint": "eslint src", 29 | "test": "mocha --compilers js:babel-register tests/index.js", 30 | "bundle": "webpack -p --colors --progress", 31 | "start": "webpack-dev-server -d --colors --inline --content-base public", 32 | "build": "npm run lint && npm run bundle" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /step-4-done/public/css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Roboto', sans-serif; 3 | } 4 | -------------------------------------------------------------------------------- /step-4-done/public/img/chevrol-bel-air.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-4-done/public/img/chevrol-bel-air.png -------------------------------------------------------------------------------- /step-4-done/public/img/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-4-done/public/img/react.png -------------------------------------------------------------------------------- /step-4-done/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Workshop 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Wines

13 | 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /step-4-done/public/js/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-4-done/public/js/.gitkeep -------------------------------------------------------------------------------- /step-4-done/readme.md: -------------------------------------------------------------------------------- 1 | # Etape 4 2 | 3 | Ce dossier contient la version finale de [l'étape 4]('../step-4') 4 | -------------------------------------------------------------------------------- /step-4-done/src/app.js: -------------------------------------------------------------------------------- 1 | /* eslint react/jsx-max-props-per-line: 0 */ 2 | 3 | import 'whatwg-fetch'; 4 | 5 | import React, { PropTypes } from 'react'; 6 | 7 | import WineApp from './components/wine-app'; 8 | import { RegionsPage } from './components/regions'; 9 | import { WineListPage } from './components/wine-list'; 10 | import { WinePage } from './components/wine'; 11 | import { NotFound } from './components/not-found'; 12 | 13 | import { Router, Route, browserHistory, IndexRoute } from 'react-router'; 14 | 15 | export const App = React.createClass({ 16 | propTypes: { 17 | history: PropTypes.object, // eslint-disable-line 18 | }, 19 | render() { 20 | const history = this.props.history || browserHistory; 21 | return ( 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | ); 31 | } 32 | }); 33 | -------------------------------------------------------------------------------- /step-4-done/src/components/not-found.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const NotFound = React.createClass({ 4 | render() { 5 | return ( 6 |

Il semble que vous n'êtes pas au bon endroit !!!

7 | ); 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /step-4-done/src/components/wine-app.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | 3 | const WineApp = React.createClass({ 4 | 5 | propTypes: { 6 | children: PropTypes.element 7 | }, 8 | 9 | contextTypes: { 10 | router: React.PropTypes.object 11 | }, 12 | 13 | getInitialState() { 14 | return { 15 | title: '' 16 | }; 17 | }, 18 | 19 | setTitle(title) { 20 | this.setState({ title }); 21 | }, 22 | 23 | goBack() { 24 | this.context.router.goBack(); 25 | }, 26 | 27 | render () { 28 | return ( 29 |
30 |
31 |

{this.state.title}

32 | {this.props.children && React.cloneElement(this.props.children, { 33 | setTitle: this.setTitle 34 | })} 35 |
36 |
37 | ); 38 | } 39 | }) 40 | 41 | export default WineApp 42 | -------------------------------------------------------------------------------- /step-4-done/src/index.js: -------------------------------------------------------------------------------- 1 | import 'whatwg-fetch'; 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | import { App } from './app'; 7 | 8 | ReactDOM.render(, document.getElementById('main')); 9 | -------------------------------------------------------------------------------- /step-4-done/tests/bootstrap.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: 0 */ 2 | 3 | import jsdom from 'jsdom'; 4 | 5 | export function bootstrapEnv(body = '') { 6 | const doc = jsdom.jsdom(`${body}`); 7 | const win = doc.defaultView; 8 | function propagateToGlobal(window) { 9 | for (const key in window) { 10 | if (!window.hasOwnProperty(key)) continue; 11 | if (key in global) continue; 12 | global[key] = window[key]; 13 | } 14 | } 15 | global.document = doc; 16 | global.window = win; 17 | global.TEST = true; 18 | global.window.TEST = true; 19 | propagateToGlobal(win); 20 | // console.log('\nENV setup is done !!!'); 21 | } 22 | -------------------------------------------------------------------------------- /step-4-done/tests/index.js: -------------------------------------------------------------------------------- 1 | /* eslint no-unused-vars:0, no-console: 0 */ 2 | 3 | import { bootstrapEnv } from './bootstrap'; 4 | 5 | bootstrapEnv(); 6 | 7 | require('./components/regions.spec.js') 8 | require('./components/wine-list.spec.js') 9 | require('./components/wine.spec.js') 10 | require('./components/wine-app.spec.js') 11 | -------------------------------------------------------------------------------- /step-4-done/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | 3 | module.exports = { 4 | output: { 5 | path: './public/js/', 6 | publicPath: '/js/', 7 | filename: 'bundle.js' 8 | }, 9 | entry: { 10 | app: ['./src/index.js'] 11 | }, 12 | resolve: { 13 | extensions: ['', '.js', '.jsx'] 14 | }, 15 | module: { 16 | loaders: [ 17 | { 18 | test: /\.js$/, 19 | exclude: /node_modules/, 20 | loader: 'babel' 21 | } 22 | ] 23 | }, 24 | devServer: { 25 | historyApiFallback: true, 26 | proxy: { 27 | '/api/*': { 28 | target: 'http://localhost:3000' 29 | } 30 | } 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /step-4/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /step-4/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | webpack.config.js 3 | public 4 | README.md 5 | -------------------------------------------------------------------------------- /step-4/.gitignore: -------------------------------------------------------------------------------- 1 | # Node.js 2 | node_modules 3 | npm-debug.log 4 | 5 | # Bundles 6 | bundle.js 7 | bundle.js.map 8 | -------------------------------------------------------------------------------- /step-4/mockup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-4/mockup.png -------------------------------------------------------------------------------- /step-4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-workshop", 3 | "description": "React Workshop", 4 | "version": "0.1.0", 5 | "dependencies": { 6 | "react": "0.14.7", 7 | "react-dom": "0.14.7", 8 | "react-router": "2.0.1", 9 | "whatwg-fetch": "0.11.0" 10 | }, 11 | "devDependencies": { 12 | "babel-loader": "6.2.4", 13 | "babel-preset-es2015": "6.6.0", 14 | "babel-preset-react": "6.5.0", 15 | "babel-register": "6.7.2", 16 | "chai": "3.5.0", 17 | "enzyme": "2.2.0", 18 | "eslint": "2.4.0", 19 | "eslint-plugin-react": "4.2.3", 20 | "jsdom": "8.1.0", 21 | "mocha": "2.4.5", 22 | "react-addons-test-utils": "0.14.7", 23 | "sinon": "1.17.3", 24 | "webpack": "1.12.14", 25 | "webpack-dev-server": "1.14.1" 26 | }, 27 | "scripts": { 28 | "lint": "eslint src", 29 | "test": "mocha --compilers js:babel-register tests/index.js", 30 | "bundle": "webpack -p --colors --progress", 31 | "start": "webpack-dev-server -d --colors --inline --content-base public", 32 | "build": "npm run lint && npm run bundle" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /step-4/public/css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Roboto', sans-serif; 3 | } 4 | -------------------------------------------------------------------------------- /step-4/public/img/chevrol-bel-air.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-4/public/img/chevrol-bel-air.png -------------------------------------------------------------------------------- /step-4/public/img/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-4/public/img/react.png -------------------------------------------------------------------------------- /step-4/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Workshop 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Wines

13 | 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /step-4/public/js/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-4/public/js/.gitkeep -------------------------------------------------------------------------------- /step-4/src/app.js: -------------------------------------------------------------------------------- 1 | /* eslint react/jsx-max-props-per-line: 0 */ 2 | 3 | import 'whatwg-fetch'; 4 | 5 | import React, { PropTypes } from 'react'; 6 | 7 | import WineApp from './components/wine-app'; 8 | import { RegionsPage } from './components/regions'; 9 | import { WineListPage } from './components/wine-list'; 10 | import { WinePage } from './components/wine'; 11 | import { NotFound } from './components/not-found'; 12 | 13 | import { Router, Route, browserHistory, IndexRoute } from 'react-router'; 14 | 15 | export const App = React.createClass({ 16 | propTypes: { 17 | history: PropTypes.object, // eslint-disable-line 18 | }, 19 | render() { 20 | const history = this.props.history || browserHistory; 21 | return ( 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | ); 31 | } 32 | }); 33 | -------------------------------------------------------------------------------- /step-4/src/components/not-found.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const NotFound = React.createClass({ 4 | render() { 5 | return ( 6 |

Il semble que vous n'êtes pas au bon endroit !!!

7 | ); 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /step-4/src/components/wine-app.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | 3 | const WineApp = React.createClass({ 4 | 5 | propTypes: { 6 | children: PropTypes.element 7 | }, 8 | 9 | contextTypes: { 10 | router: React.PropTypes.object 11 | }, 12 | 13 | getInitialState() { 14 | return { 15 | title: '' 16 | }; 17 | }, 18 | 19 | setTitle(title) { 20 | this.setState({ title }); 21 | }, 22 | 23 | goBack() { 24 | this.context.router.goBack(); 25 | }, 26 | 27 | render () { 28 | return ( 29 |
30 |
31 |

{this.state.title}

32 | {this.props.children && React.cloneElement(this.props.children, { 33 | setTitle: this.setTitle 34 | })} 35 |
36 |
37 | ); 38 | } 39 | }) 40 | 41 | export default WineApp 42 | -------------------------------------------------------------------------------- /step-4/src/index.js: -------------------------------------------------------------------------------- 1 | import 'whatwg-fetch'; 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | import { App } from './app'; 7 | 8 | ReactDOM.render(, document.getElementById('main')); 9 | -------------------------------------------------------------------------------- /step-4/tests/bootstrap.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: 0 */ 2 | 3 | import jsdom from 'jsdom'; 4 | 5 | export function bootstrapEnv(body = '') { 6 | const doc = jsdom.jsdom(`${body}`); 7 | const win = doc.defaultView; 8 | function propagateToGlobal(window) { 9 | for (const key in window) { 10 | if (!window.hasOwnProperty(key)) continue; 11 | if (key in global) continue; 12 | global[key] = window[key]; 13 | } 14 | } 15 | global.document = doc; 16 | global.window = win; 17 | global.TEST = true; 18 | global.window.TEST = true; 19 | propagateToGlobal(win); 20 | // console.log('\nENV setup is done !!!'); 21 | } 22 | -------------------------------------------------------------------------------- /step-4/tests/index.js: -------------------------------------------------------------------------------- 1 | /* eslint no-unused-vars:0, no-console: 0 */ 2 | 3 | import { bootstrapEnv } from './bootstrap'; 4 | 5 | bootstrapEnv(); 6 | 7 | require('./components/regions.spec.js') 8 | require('./components/wine-list.spec.js') 9 | require('./components/wine.spec.js') 10 | require('./components/wine-app.spec.js') 11 | -------------------------------------------------------------------------------- /step-4/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | 3 | module.exports = { 4 | output: { 5 | path: './public/js/', 6 | publicPath: '/js/', 7 | filename: 'bundle.js' 8 | }, 9 | entry: { 10 | app: ['./src/index.js'] 11 | }, 12 | resolve: { 13 | extensions: ['', '.js', '.jsx'] 14 | }, 15 | module: { 16 | loaders: [ 17 | { 18 | test: /\.js$/, 19 | exclude: /node_modules/, 20 | loader: 'babel' 21 | } 22 | ] 23 | }, 24 | devServer: { 25 | historyApiFallback: true, 26 | proxy: { 27 | '/api/*': { 28 | target: 'http://localhost:3000' 29 | } 30 | } 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /step-5-done/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /step-5-done/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | webpack.config.js 3 | public 4 | README.md 5 | -------------------------------------------------------------------------------- /step-5-done/.gitignore: -------------------------------------------------------------------------------- 1 | # Node.js 2 | node_modules 3 | npm-debug.log 4 | 5 | # Bundles 6 | bundle.js 7 | bundle.js.map 8 | -------------------------------------------------------------------------------- /step-5-done/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-workshop", 3 | "description": "React Workshop", 4 | "version": "0.1.0", 5 | "dependencies": { 6 | "react": "0.14.7", 7 | "react-dom": "0.14.7", 8 | "react-redux": "4.4.1", 9 | "react-router": "2.0.1", 10 | "redux": "3.3.1", 11 | "whatwg-fetch": "0.11.0" 12 | }, 13 | "devDependencies": { 14 | "babel-loader": "6.2.4", 15 | "babel-preset-es2015": "6.6.0", 16 | "babel-preset-react": "6.5.0", 17 | "babel-register": "6.7.2", 18 | "chai": "3.5.0", 19 | "enzyme": "2.2.0", 20 | "eslint": "2.4.0", 21 | "eslint-plugin-react": "4.2.3", 22 | "jsdom": "8.1.0", 23 | "mocha": "2.4.5", 24 | "react-addons-test-utils": "0.14.7", 25 | "sinon": "1.17.3", 26 | "webpack": "1.12.14", 27 | "webpack-dev-server": "1.14.1" 28 | }, 29 | "scripts": { 30 | "lint": "eslint src", 31 | "test": "mocha --compilers js:babel-register tests/index.js", 32 | "bundle": "webpack -p --colors --progress", 33 | "start": "webpack-dev-server -d --colors --inline --content-base public", 34 | "build": "npm run lint && npm run bundle" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /step-5-done/public/css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Roboto', sans-serif; 3 | } 4 | -------------------------------------------------------------------------------- /step-5-done/public/img/chevrol-bel-air.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-5-done/public/img/chevrol-bel-air.png -------------------------------------------------------------------------------- /step-5-done/public/img/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-5-done/public/img/react.png -------------------------------------------------------------------------------- /step-5-done/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Workshop 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Wines

13 | 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /step-5-done/public/js/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-5-done/public/js/.gitkeep -------------------------------------------------------------------------------- /step-5-done/readme.md: -------------------------------------------------------------------------------- 1 | # Etape 5 2 | 3 | Ce dossier contient la version finale de [l'étape 5]('../step-5') 4 | -------------------------------------------------------------------------------- /step-5-done/src/actions/index.js: -------------------------------------------------------------------------------- 1 | export const addLike = () => { 2 | return { 3 | type: 'ADD_LIKE', 4 | increment: 1 5 | }; 6 | } 7 | 8 | export const removeLike = () => { 9 | return { 10 | type: 'REMOVE_LIKE', 11 | decrement: 1 12 | }; 13 | } 14 | 15 | export const setLikes = (likes) => { 16 | return { 17 | type: 'SET_LIKES', 18 | likes 19 | }; 20 | } 21 | 22 | export const addComment = () => { 23 | return { 24 | type: 'ADD_COMMENT', 25 | increment: 1 26 | }; 27 | } 28 | 29 | export const setComments = (comments) => { 30 | return { 31 | type: 'SET_COMMENTS', 32 | comments 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /step-5-done/src/components/not-found.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const NotFound = React.createClass({ 4 | render() { 5 | return ( 6 |

Il semble que vous n'êtes pas au bon endroit !!!

7 | ); 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /step-5-done/src/components/stats.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import { connect } from 'react-redux'; 3 | 4 | export const Stats = React.createClass({ 5 | propTypes: { 6 | comments: PropTypes.number.isRequired, 7 | likes: PropTypes.number.isRequired 8 | }, 9 | 10 | render() { 11 | return ( 12 |
13 |

Global stats

14 |
comments : {this.props.comments}
15 |
likes : {this.props.likes}
16 |
17 | ); 18 | } 19 | }); 20 | 21 | const mapStateToProps = (state) => { 22 | return { 23 | comments: state.comments, 24 | likes: state.likes 25 | }; 26 | }; 27 | 28 | export const GlobalStats = connect(mapStateToProps)(Stats); 29 | -------------------------------------------------------------------------------- /step-5-done/src/index.js: -------------------------------------------------------------------------------- 1 | import 'whatwg-fetch'; 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | import { App } from './app'; 7 | 8 | ReactDOM.render(, document.getElementById('main')); 9 | -------------------------------------------------------------------------------- /step-5-done/src/reducers/comments.js: -------------------------------------------------------------------------------- 1 | const comments = (state = 0, action) => { 2 | switch (action.type) { 3 | case 'ADD_COMMENT': 4 | return state + action.increment; 5 | case 'SET_COMMENTS': 6 | return action.comments; 7 | default: 8 | return state; 9 | } 10 | } 11 | 12 | export default comments; 13 | -------------------------------------------------------------------------------- /step-5-done/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import comments from './comments'; 3 | import likes from './likes'; 4 | 5 | const app = combineReducers({ 6 | comments, 7 | likes 8 | }); 9 | 10 | export default app; 11 | -------------------------------------------------------------------------------- /step-5-done/src/reducers/likes.js: -------------------------------------------------------------------------------- 1 | const likes = (state = 0, action) => { 2 | switch (action.type) { 3 | case 'ADD_LIKE': 4 | return state + action.increment; 5 | case 'REMOVE_LIKE': 6 | return state - action.decrement; 7 | case 'SET_LIKES': 8 | return action.likes; 9 | default: 10 | return state; 11 | } 12 | } 13 | 14 | export default likes; 15 | -------------------------------------------------------------------------------- /step-5-done/tests/bootstrap.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: 0 */ 2 | 3 | import jsdom from 'jsdom'; 4 | 5 | export function bootstrapEnv(body = '') { 6 | const doc = jsdom.jsdom(`${body}`); 7 | const win = doc.defaultView; 8 | function propagateToGlobal(window) { 9 | for (const key in window) { 10 | if (!window.hasOwnProperty(key)) continue; 11 | if (key in global) continue; 12 | global[key] = window[key]; 13 | } 14 | } 15 | global.document = doc; 16 | global.window = win; 17 | global.TEST = true; 18 | global.window.TEST = true; 19 | propagateToGlobal(win); 20 | // console.log('\nENV setup is done !!!'); 21 | } 22 | -------------------------------------------------------------------------------- /step-5-done/tests/index.js: -------------------------------------------------------------------------------- 1 | /* eslint no-unused-vars:0, no-console: 0 */ 2 | 3 | import { bootstrapEnv } from './bootstrap'; 4 | 5 | bootstrapEnv(); 6 | 7 | require('./components/regions.spec.js') 8 | require('./components/wine-list.spec.js') 9 | require('./components/wine.spec.js') 10 | require('./components/wine-app.spec.js') 11 | -------------------------------------------------------------------------------- /step-5-done/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | 3 | module.exports = { 4 | output: { 5 | path: './public/js/', 6 | publicPath: '/js/', 7 | filename: 'bundle.js' 8 | }, 9 | entry: { 10 | app: ['./src/index.js'] 11 | }, 12 | resolve: { 13 | extensions: ['', '.js', '.jsx'] 14 | }, 15 | module: { 16 | loaders: [ 17 | { 18 | test: /\.js$/, 19 | exclude: /node_modules/, 20 | loader: 'babel' 21 | } 22 | ] 23 | }, 24 | devServer: { 25 | historyApiFallback: true, 26 | proxy: { 27 | '/api/*': { 28 | target: 'http://localhost:3000' 29 | } 30 | } 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /step-5/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /step-5/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | webpack.config.js 3 | public 4 | README.md 5 | -------------------------------------------------------------------------------- /step-5/.gitignore: -------------------------------------------------------------------------------- 1 | # Node.js 2 | node_modules 3 | npm-debug.log 4 | 5 | # Bundles 6 | bundle.js 7 | bundle.js.map 8 | -------------------------------------------------------------------------------- /step-5/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-workshop", 3 | "description": "React Workshop", 4 | "version": "0.1.0", 5 | "dependencies": { 6 | "react": "0.14.7", 7 | "react-dom": "0.14.7", 8 | "react-redux": "4.4.1", 9 | "react-router": "2.0.1", 10 | "redux": "3.3.1", 11 | "whatwg-fetch": "0.11.0" 12 | }, 13 | "devDependencies": { 14 | "babel-loader": "6.2.4", 15 | "babel-preset-es2015": "6.6.0", 16 | "babel-preset-react": "6.5.0", 17 | "babel-register": "6.7.2", 18 | "chai": "3.5.0", 19 | "enzyme": "2.2.0", 20 | "eslint": "2.4.0", 21 | "eslint-plugin-react": "4.2.3", 22 | "jsdom": "8.1.0", 23 | "mocha": "2.4.5", 24 | "react-addons-test-utils": "0.14.7", 25 | "sinon": "1.17.3", 26 | "webpack": "1.12.14", 27 | "webpack-dev-server": "1.14.1" 28 | }, 29 | "scripts": { 30 | "lint": "eslint src", 31 | "test": "mocha --compilers js:babel-register tests/index.js", 32 | "bundle": "webpack -p --colors --progress", 33 | "start": "webpack-dev-server -d --colors --inline --content-base public", 34 | "build": "npm run lint && npm run bundle" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /step-5/public/css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Roboto', sans-serif; 3 | } 4 | -------------------------------------------------------------------------------- /step-5/public/img/chevrol-bel-air.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-5/public/img/chevrol-bel-air.png -------------------------------------------------------------------------------- /step-5/public/img/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-5/public/img/react.png -------------------------------------------------------------------------------- /step-5/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Workshop 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Wines

13 | 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /step-5/public/js/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-5/public/js/.gitkeep -------------------------------------------------------------------------------- /step-5/src/actions/index.js: -------------------------------------------------------------------------------- 1 | export const increment = () => { 2 | return { 3 | type: 'INCREMENT', 4 | increment: 1 5 | }; 6 | } 7 | -------------------------------------------------------------------------------- /step-5/src/components/clicker.js: -------------------------------------------------------------------------------- 1 | import { increment } from '../actions'; 2 | import { connect } from 'react-redux'; 3 | import React, { PropTypes } from 'react'; 4 | 5 | const SimpleClicker = React.createClass({ 6 | propTypes: { 7 | counter: PropTypes.number, 8 | dispatch: PropTypes.func 9 | }, 10 | handleButtonClick() { 11 | this.props.dispatch(increment()); 12 | }, 13 | render() { 14 | return ( 15 |
16 | Clicked : {this.props.counter} 17 | 18 |
19 | ); 20 | } 21 | }); 22 | 23 | const mapStateToProps = (state) => { 24 | return { 25 | counter: state.counter 26 | } 27 | }; 28 | 29 | export const Clicker = connect(mapStateToProps)(SimpleClicker); 30 | -------------------------------------------------------------------------------- /step-5/src/components/not-found.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const NotFound = React.createClass({ 4 | render() { 5 | return ( 6 |

Il semble que vous n'êtes pas au bon endroit !!!

7 | ); 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /step-5/src/index.js: -------------------------------------------------------------------------------- 1 | import 'whatwg-fetch'; 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | import { App } from './app'; 7 | 8 | ReactDOM.render(, document.getElementById('main')); 9 | -------------------------------------------------------------------------------- /step-5/src/reducers/counter.js: -------------------------------------------------------------------------------- 1 | const counter = (state = 0, action) => { 2 | switch (action.type) { 3 | case 'INCREMENT': 4 | return state + action.increment; 5 | default: 6 | return state; 7 | } 8 | } 9 | 10 | export default counter; 11 | -------------------------------------------------------------------------------- /step-5/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import counter from './counter'; 3 | 4 | const app = combineReducers({ 5 | counter 6 | }); 7 | 8 | export default app; 9 | -------------------------------------------------------------------------------- /step-5/tests/bootstrap.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: 0 */ 2 | 3 | import jsdom from 'jsdom'; 4 | 5 | export function bootstrapEnv(body = '') { 6 | const doc = jsdom.jsdom(`${body}`); 7 | const win = doc.defaultView; 8 | function propagateToGlobal(window) { 9 | for (const key in window) { 10 | if (!window.hasOwnProperty(key)) continue; 11 | if (key in global) continue; 12 | global[key] = window[key]; 13 | } 14 | } 15 | global.document = doc; 16 | global.window = win; 17 | global.TEST = true; 18 | global.window.TEST = true; 19 | propagateToGlobal(win); 20 | // console.log('\nENV setup is done !!!'); 21 | } 22 | -------------------------------------------------------------------------------- /step-5/tests/index.js: -------------------------------------------------------------------------------- 1 | /* eslint no-unused-vars:0, no-console: 0 */ 2 | 3 | import { bootstrapEnv } from './bootstrap'; 4 | 5 | bootstrapEnv(); 6 | 7 | require('./components/regions.spec.js') 8 | require('./components/wine-list.spec.js') 9 | require('./components/wine.spec.js') 10 | require('./components/wine-app.spec.js') 11 | -------------------------------------------------------------------------------- /step-5/view1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-5/view1.png -------------------------------------------------------------------------------- /step-5/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | 3 | module.exports = { 4 | output: { 5 | path: './public/js/', 6 | publicPath: '/js/', 7 | filename: 'bundle.js' 8 | }, 9 | entry: { 10 | app: ['./src/index.js'] 11 | }, 12 | resolve: { 13 | extensions: ['', '.js', '.jsx'] 14 | }, 15 | module: { 16 | loaders: [ 17 | { 18 | test: /\.js$/, 19 | exclude: /node_modules/, 20 | loader: 'babel' 21 | } 22 | ] 23 | }, 24 | devServer: { 25 | historyApiFallback: true, 26 | proxy: { 27 | '/api/*': { 28 | target: 'http://localhost:3000' 29 | } 30 | } 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /step-6-done/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /step-6-done/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | webpack.config.js 3 | public 4 | README.md 5 | -------------------------------------------------------------------------------- /step-6-done/.gitignore: -------------------------------------------------------------------------------- 1 | # Node.js 2 | node_modules 3 | npm-debug.log 4 | 5 | # Bundles 6 | bundle.js 7 | bundle.js.map 8 | -------------------------------------------------------------------------------- /step-6-done/public/css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Roboto', sans-serif; 3 | } 4 | -------------------------------------------------------------------------------- /step-6-done/public/img/chevrol-bel-air.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-6-done/public/img/chevrol-bel-air.png -------------------------------------------------------------------------------- /step-6-done/public/img/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-6-done/public/img/react.png -------------------------------------------------------------------------------- /step-6-done/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Workshop 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Wines

13 | 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /step-6-done/public/js/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-6-done/public/js/.gitkeep -------------------------------------------------------------------------------- /step-6-done/readme.md: -------------------------------------------------------------------------------- 1 | # Etape 6 2 | 3 | Ce dossier contient la version finale de [l'étape 6]('../step-6') 4 | -------------------------------------------------------------------------------- /step-6-done/src/components/devtools.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { createDevTools } from 'redux-devtools'; 3 | import LogMonitor from 'redux-devtools-log-monitor'; 4 | import DockMonitor from 'redux-devtools-dock-monitor'; 5 | 6 | export const DevTools = createDevTools( 7 | 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /step-6-done/src/components/not-found.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const NotFound = React.createClass({ 4 | render() { 5 | return ( 6 |

Il semble que vous n'êtes pas au bon endroit !!!

7 | ); 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /step-6-done/src/components/stats.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import { connect } from 'react-redux'; 3 | 4 | const mapStateToProps = (state) => { 5 | return { 6 | comments: state.comments.count, 7 | likes: state.likes.count 8 | }; 9 | } 10 | 11 | export const GlobalStats = connect(mapStateToProps)(React.createClass({ 12 | propTypes: { 13 | comments: PropTypes.number.isRequired, 14 | likes: PropTypes.number.isRequired 15 | }, 16 | 17 | render() { 18 | return ( 19 |
20 |

Global stats

21 |
comments : {this.props.comments}
22 |
likes : {this.props.likes}
23 |
24 | ); 25 | } 26 | })) 27 | -------------------------------------------------------------------------------- /step-6-done/src/index.js: -------------------------------------------------------------------------------- 1 | import 'whatwg-fetch'; 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | import { App } from './app'; 7 | 8 | ReactDOM.render(, document.getElementById('main')); 9 | -------------------------------------------------------------------------------- /step-6-done/src/reducers/comments.js: -------------------------------------------------------------------------------- 1 | export const comments = (state = { count: 0 }, action) => { 2 | switch (action.type) { 3 | case 'ADD_COMMENT': 4 | return Object.assign({}, state, { count: state.count + action.increment }); 5 | case 'SET_COMMENTS': 6 | return Object.assign({}, state, { count: action.comments }); 7 | default: 8 | return state; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /step-6-done/src/reducers/http.js: -------------------------------------------------------------------------------- 1 | export const http = (state = { state: 'LOADED', error: undefined }, action) => { 2 | switch (action.type) { 3 | case 'LOADING': 4 | return Object.assign({}, state, { state: 'LOADING', error: undefined }); 5 | case 'LOADED': 6 | return Object.assign({}, state, { state: 'LOADED', error: undefined }); 7 | case 'ERROR': 8 | return Object.assign({}, state, { state: 'ERROR', error: action.error }); 9 | default: 10 | return state; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /step-6-done/src/reducers/likes.js: -------------------------------------------------------------------------------- 1 | export const likes = (state = { count: 0 }, action) => { 2 | switch (action.type) { 3 | case 'ADD_LIKE': 4 | return Object.assign({}, state, { count: state.count + action.increment }); 5 | case 'REMOVE_LIKE': 6 | return Object.assign({}, state, { count: state.count - action.decrement }); 7 | case 'SET_LIKES': 8 | return Object.assign({}, state, { count: action.likes }); 9 | default: 10 | return state; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /step-6-done/src/reducers/regions.js: -------------------------------------------------------------------------------- 1 | export const regions = (state = { data: [], lastUpdated: 0 }, action) => { 2 | switch (action.type) { 3 | case 'SET_REGIONS': 4 | return Object.assign({}, state, { data: action.regions }); 5 | case 'UPDATE_REGIONS_TIMESTAMP': 6 | return Object.assign({}, state, { lastUpdated: Date.now() }); 7 | default: 8 | return state; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /step-6-done/src/reducers/title.js: -------------------------------------------------------------------------------- 1 | export const title = (state = '', action) => { 2 | switch (action.type) { 3 | case 'SET_TITLE': 4 | return action.title; 5 | default: 6 | return state; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /step-6-done/src/reducers/wines.js: -------------------------------------------------------------------------------- 1 | export const wines = (state = {}, action) => { 2 | switch (action.type) { 3 | case 'SET_WINES': 4 | return Object.assign({}, state, { [action.region]: { lastUpdated: Date.now(), data: action.wines }}); 5 | case 'UPDATE_WINES_TIMESTAMP': 6 | return Object.assign({}, state, Object.assign({}, state[action.region], { lastUpdated: Date.now() })); 7 | default: 8 | return state; 9 | } 10 | } 11 | 12 | export const currentWine = (state = { wine: undefined, comments: [], liked: false }, action) => { 13 | switch (action.type) { 14 | case 'SET_CURRENT_WINE': 15 | return Object.assign({}, state, { wine: action.wine, liked: false }); 16 | case 'SET_CURRENT_COMMENTS': 17 | return Object.assign({}, state, { comments: action.comments }); 18 | case 'SET_CURRENT_LIKED': 19 | return Object.assign({}, state, { liked: action.liked }); 20 | default: 21 | return state; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /step-6-done/tests/bootstrap.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: 0 */ 2 | 3 | import jsdom from 'jsdom'; 4 | 5 | export function bootstrapEnv(body = '') { 6 | const doc = jsdom.jsdom(`${body}`); 7 | const win = doc.defaultView; 8 | function propagateToGlobal(window) { 9 | for (const key in window) { 10 | if (!window.hasOwnProperty(key)) continue; 11 | if (key in global) continue; 12 | global[key] = window[key]; 13 | } 14 | } 15 | global.document = doc; 16 | global.window = win; 17 | global.TEST = true; 18 | global.window.TEST = true; 19 | propagateToGlobal(win); 20 | // console.log('\nENV setup is done !!!'); 21 | } 22 | -------------------------------------------------------------------------------- /step-6-done/tests/index.js: -------------------------------------------------------------------------------- 1 | /* eslint no-unused-vars:0, no-console: 0 */ 2 | 3 | import { bootstrapEnv } from './bootstrap'; 4 | 5 | bootstrapEnv(); 6 | 7 | require('./components/regions.spec.js') 8 | require('./components/wine-list.spec.js') 9 | require('./components/wine.spec.js') 10 | require('./components/wine-app.spec.js') 11 | -------------------------------------------------------------------------------- /step-6-done/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | 3 | module.exports = { 4 | output: { 5 | path: './public/js/', 6 | publicPath: '/js/', 7 | filename: 'bundle.js' 8 | }, 9 | devServer: { 10 | historyApiFallback: true, 11 | proxy: { 12 | '/api/*': { 13 | target: 'http://localhost:3000' 14 | } 15 | } 16 | }, 17 | entry: { 18 | app: ['./src/index.js'] 19 | }, 20 | resolve: { 21 | extensions: ['', '.js', '.jsx'] 22 | }, 23 | module: { 24 | loaders: [{ 25 | test: /\.js$/, 26 | exclude: /node_modules/, 27 | loader: 'babel' 28 | }] 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /step-6/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /step-6/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | webpack.config.js 3 | public 4 | README.md 5 | -------------------------------------------------------------------------------- /step-6/.gitignore: -------------------------------------------------------------------------------- 1 | # Node.js 2 | node_modules 3 | npm-debug.log 4 | 5 | # Bundles 6 | bundle.js 7 | bundle.js.map 8 | -------------------------------------------------------------------------------- /step-6/public/css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Roboto', sans-serif; 3 | } 4 | -------------------------------------------------------------------------------- /step-6/public/img/chevrol-bel-air.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-6/public/img/chevrol-bel-air.png -------------------------------------------------------------------------------- /step-6/public/img/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-6/public/img/react.png -------------------------------------------------------------------------------- /step-6/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Workshop 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Wines

13 | 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /step-6/public/js/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-6/public/js/.gitkeep -------------------------------------------------------------------------------- /step-6/src/components/devtools.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { createDevTools } from 'redux-devtools'; 3 | import LogMonitor from 'redux-devtools-log-monitor'; 4 | import DockMonitor from 'redux-devtools-dock-monitor'; 5 | 6 | export const DevTools = createDevTools( 7 | 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /step-6/src/components/not-found.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const NotFound = React.createClass({ 4 | render() { 5 | return ( 6 |

Il semble que vous n'êtes pas au bon endroit !!!

7 | ); 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /step-6/src/components/stats.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import { connect } from 'react-redux'; 3 | 4 | const mapStateToProps = (state) => { 5 | return { 6 | comments: state.comments.count, 7 | likes: state.likes.count 8 | }; 9 | } 10 | 11 | export const GlobalStats = connect(mapStateToProps)(React.createClass({ 12 | propTypes: { 13 | comments: PropTypes.number.isRequired, 14 | likes: PropTypes.number.isRequired 15 | }, 16 | 17 | render() { 18 | return ( 19 |
20 |

Global stats

21 |
comments : {this.props.comments}
22 |
likes : {this.props.likes}
23 |
24 | ); 25 | } 26 | })) 27 | -------------------------------------------------------------------------------- /step-6/src/index.js: -------------------------------------------------------------------------------- 1 | import 'whatwg-fetch'; 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | import { App } from './app'; 7 | 8 | ReactDOM.render(, document.getElementById('main')); 9 | -------------------------------------------------------------------------------- /step-6/src/reducers/comments.js: -------------------------------------------------------------------------------- 1 | export const comments = (state = { count: 0 }, action) => { 2 | switch (action.type) { 3 | case 'ADD_COMMENT': 4 | return Object.assign({}, state, { count: state.count + action.increment }); 5 | case 'SET_COMMENTS': 6 | return Object.assign({}, state, { count: action.comments }); 7 | default: 8 | return state; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /step-6/src/reducers/http.js: -------------------------------------------------------------------------------- 1 | export const http = (state = { state: 'LOADED', error: undefined }, action) => { 2 | switch (action.type) { 3 | case 'LOADING': 4 | return Object.assign({}, state, { state: 'LOADING', error: undefined }); 5 | case 'LOADED': 6 | return Object.assign({}, state, { state: 'LOADED', error: undefined }); 7 | case 'ERROR': 8 | return Object.assign({}, state, { state: 'ERROR', error: action.error }); 9 | default: 10 | return state; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /step-6/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import { comments } from './comments'; 3 | import { likes } from './likes'; 4 | import { http } from './http'; 5 | import { routerReducer } from 'react-router-redux'; 6 | 7 | export const app = combineReducers({ 8 | comments, 9 | likes, 10 | http, 11 | routing: routerReducer 12 | }) 13 | -------------------------------------------------------------------------------- /step-6/src/reducers/likes.js: -------------------------------------------------------------------------------- 1 | export const likes = (state = { count: 0 }, action) => { 2 | switch (action.type) { 3 | case 'ADD_LIKE': 4 | return Object.assign({}, state, { count: state.count + action.increment }); 5 | case 'REMOVE_LIKE': 6 | return Object.assign({}, state, { count: state.count - action.decrement }); 7 | case 'SET_LIKES': 8 | return Object.assign({}, state, { count: action.likes }); 9 | default: 10 | return state; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /step-6/tests/bootstrap.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: 0 */ 2 | 3 | import jsdom from 'jsdom'; 4 | 5 | export function bootstrapEnv(body = '') { 6 | const doc = jsdom.jsdom(`${body}`); 7 | const win = doc.defaultView; 8 | function propagateToGlobal(window) { 9 | for (const key in window) { 10 | if (!window.hasOwnProperty(key)) continue; 11 | if (key in global) continue; 12 | global[key] = window[key]; 13 | } 14 | } 15 | global.document = doc; 16 | global.window = win; 17 | global.TEST = true; 18 | global.window.TEST = true; 19 | propagateToGlobal(win); 20 | // console.log('\nENV setup is done !!!'); 21 | } 22 | -------------------------------------------------------------------------------- /step-6/tests/index.js: -------------------------------------------------------------------------------- 1 | /* eslint no-unused-vars:0, no-console: 0 */ 2 | 3 | import { bootstrapEnv } from './bootstrap'; 4 | 5 | bootstrapEnv(); 6 | 7 | require('./components/regions.spec.js') 8 | require('./components/wine-list.spec.js') 9 | require('./components/wine.spec.js') 10 | require('./components/wine-app.spec.js') 11 | -------------------------------------------------------------------------------- /step-6/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | 3 | module.exports = { 4 | output: { 5 | path: './public/js/', 6 | publicPath: '/js/', 7 | filename: 'bundle.js' 8 | }, 9 | entry: { 10 | app: ['./src/index.js'] 11 | }, 12 | resolve: { 13 | extensions: ['', '.js', '.jsx'] 14 | }, 15 | module: { 16 | loaders: [ 17 | { 18 | test: /\.js$/, 19 | exclude: /node_modules/, 20 | loader: 'babel' 21 | } 22 | ] 23 | }, 24 | devServer: { 25 | historyApiFallback: true, 26 | proxy: { 27 | '/api/*': { 28 | target: 'http://localhost:3000' 29 | } 30 | } 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /step-7/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /step-7/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | webpack.config.js 3 | public 4 | README.md 5 | -------------------------------------------------------------------------------- /step-7/.gitignore: -------------------------------------------------------------------------------- 1 | # Node.js 2 | node_modules 3 | npm-debug.log 4 | 5 | # Bundles 6 | bundle.js 7 | bundle.js.map 8 | -------------------------------------------------------------------------------- /step-7/public/css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Roboto', sans-serif; 3 | } 4 | -------------------------------------------------------------------------------- /step-7/public/img/chevrol-bel-air.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-7/public/img/chevrol-bel-air.png -------------------------------------------------------------------------------- /step-7/public/img/react.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-7/public/img/react.png -------------------------------------------------------------------------------- /step-7/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React Workshop 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Wines

13 | 14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /step-7/public/js/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-7/public/js/.gitkeep -------------------------------------------------------------------------------- /step-7/src/components/devtools.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { createDevTools } from 'redux-devtools'; 3 | import LogMonitor from 'redux-devtools-log-monitor'; 4 | import DockMonitor from 'redux-devtools-dock-monitor'; 5 | 6 | export const DevTools = createDevTools( 7 | 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /step-7/src/components/not-found.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const NotFound = React.createClass({ 4 | render() { 5 | return ( 6 |

Il semble que vous n'êtes pas au bon endroit !!!

7 | ); 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /step-7/src/components/stats.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes } from 'react'; 2 | import { connect } from 'react-redux'; 3 | 4 | const mapStateToProps = (state) => { 5 | return { 6 | comments: state.comments.count, 7 | likes: state.likes.count 8 | }; 9 | } 10 | 11 | export const GlobalStats = connect(mapStateToProps)(React.createClass({ 12 | propTypes: { 13 | comments: PropTypes.number.isRequired, 14 | likes: PropTypes.number.isRequired 15 | }, 16 | 17 | render() { 18 | return ( 19 |
20 |

Global stats

21 |
comments : {this.props.comments}
22 |
likes : {this.props.likes}
23 |
24 | ); 25 | } 26 | })) 27 | -------------------------------------------------------------------------------- /step-7/src/index.js: -------------------------------------------------------------------------------- 1 | import 'whatwg-fetch'; 2 | 3 | import React from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | import { App } from './app'; 7 | 8 | ReactDOM.render(, document.getElementById('main')); 9 | -------------------------------------------------------------------------------- /step-7/src/reducers/comments.js: -------------------------------------------------------------------------------- 1 | export const comments = (state = { count: 0 }, action) => { 2 | switch (action.type) { 3 | case 'ADD_COMMENT': 4 | return Object.assign({}, state, { count: state.count + action.increment }); 5 | case 'SET_COMMENTS': 6 | return Object.assign({}, state, { count: action.comments }); 7 | default: 8 | return state; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /step-7/src/reducers/http.js: -------------------------------------------------------------------------------- 1 | export const http = (state = { state: 'LOADED', error: undefined }, action) => { 2 | switch (action.type) { 3 | case 'LOADING': 4 | return Object.assign({}, state, { state: 'LOADING', error: undefined }); 5 | case 'LOADED': 6 | return Object.assign({}, state, { state: 'LOADED', error: undefined }); 7 | case 'ERROR': 8 | return Object.assign({}, state, { state: 'ERROR', error: action.error }); 9 | default: 10 | return state; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /step-7/src/reducers/likes.js: -------------------------------------------------------------------------------- 1 | export const likes = (state = { count: 0 }, action) => { 2 | switch (action.type) { 3 | case 'ADD_LIKE': 4 | return Object.assign({}, state, { count: state.count + action.increment }); 5 | case 'REMOVE_LIKE': 6 | return Object.assign({}, state, { count: state.count - action.decrement }); 7 | case 'SET_LIKES': 8 | return Object.assign({}, state, { count: action.likes }); 9 | default: 10 | return state; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /step-7/src/reducers/regions.js: -------------------------------------------------------------------------------- 1 | export const regions = (state = { data: [], lastUpdated: 0 }, action) => { 2 | switch (action.type) { 3 | case 'SET_REGIONS': 4 | return Object.assign({}, state, { data: action.regions }); 5 | case 'UPDATE_REGIONS_TIMESTAMP': 6 | return Object.assign({}, state, { lastUpdated: Date.now() }); 7 | default: 8 | return state; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /step-7/src/reducers/title.js: -------------------------------------------------------------------------------- 1 | export const title = (state = '', action) => { 2 | switch (action.type) { 3 | case 'SET_TITLE': 4 | return action.title; 5 | default: 6 | return state; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /step-7/src/reducers/wines.js: -------------------------------------------------------------------------------- 1 | export const wines = (state = {}, action) => { 2 | switch (action.type) { 3 | case 'SET_WINES': 4 | return Object.assign({}, state, { [action.region]: { lastUpdated: Date.now(), data: action.wines }}); 5 | case 'UPDATE_WINES_TIMESTAMP': 6 | return Object.assign({}, state, Object.assign({}, state[action.region], { lastUpdated: Date.now() })); 7 | default: 8 | return state; 9 | } 10 | } 11 | 12 | export const currentWine = (state = { wine: undefined, comments: [], liked: false }, action) => { 13 | switch (action.type) { 14 | case 'SET_CURRENT_WINE': 15 | return Object.assign({}, state, { wine: action.wine, liked: false }); 16 | case 'SET_CURRENT_COMMENTS': 17 | return Object.assign({}, state, { comments: action.comments }); 18 | case 'SET_CURRENT_LIKED': 19 | return Object.assign({}, state, { liked: action.liked }); 20 | default: 21 | return state; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /step-7/tests/bootstrap.js: -------------------------------------------------------------------------------- 1 | /* eslint no-console: 0 */ 2 | 3 | import jsdom from 'jsdom'; 4 | 5 | export function bootstrapEnv(body = '') { 6 | const doc = jsdom.jsdom(`${body}`); 7 | const win = doc.defaultView; 8 | function propagateToGlobal(window) { 9 | for (const key in window) { 10 | if (!window.hasOwnProperty(key)) continue; 11 | if (key in global) continue; 12 | global[key] = window[key]; 13 | } 14 | } 15 | global.document = doc; 16 | global.window = win; 17 | global.TEST = true; 18 | global.window.TEST = true; 19 | propagateToGlobal(win); 20 | // console.log('\nENV setup is done !!!'); 21 | } 22 | -------------------------------------------------------------------------------- /step-7/tests/index.js: -------------------------------------------------------------------------------- 1 | /* eslint no-unused-vars:0, no-console: 0 */ 2 | 3 | import { bootstrapEnv } from './bootstrap'; 4 | 5 | bootstrapEnv(); 6 | 7 | require('./components/regions.spec.js') 8 | require('./components/wine-list.spec.js') 9 | require('./components/wine.spec.js') 10 | require('./components/wine-app.spec.js') 11 | -------------------------------------------------------------------------------- /step-7/webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | 3 | module.exports = { 4 | output: { 5 | path: './public/js/', 6 | publicPath: '/js/', 7 | filename: 'bundle.js' 8 | }, 9 | devServer: { 10 | historyApiFallback: true, 11 | proxy: { 12 | '/api/*': { 13 | target: 'http://localhost:3000' 14 | } 15 | } 16 | }, 17 | entry: { 18 | app: ['./src/index.js'] 19 | }, 20 | resolve: { 21 | extensions: ['', '.js', '.jsx'] 22 | }, 23 | module: { 24 | loaders: [{ 25 | test: /\.js$/, 26 | exclude: /node_modules/, 27 | loader: 'babel' 28 | }] 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /step-8-done/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | webpack.config.js 3 | public 4 | README.md 5 | -------------------------------------------------------------------------------- /step-8-done/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | project.xcworkspace 24 | 25 | # Android/IJ 26 | # 27 | .idea 28 | .gradle 29 | local.properties 30 | 31 | # node.js 32 | # 33 | node_modules/ 34 | npm-debug.log 35 | -------------------------------------------------------------------------------- /step-8-done/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /step-8-done/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 11 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /step-8-done/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8-done/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /step-8-done/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8-done/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /step-8-done/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8-done/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /step-8-done/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8-done/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /step-8-done/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | wines 3 | 4 | -------------------------------------------------------------------------------- /step-8-done/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /step-8-done/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.3.1' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | mavenLocal() 18 | jcenter() 19 | maven { 20 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 21 | url "$projectDir/../../node_modules/react-native/android" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /step-8-done/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | android.useDeprecatedNdk=true 21 | -------------------------------------------------------------------------------- /step-8-done/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8-done/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /step-8-done/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip 6 | -------------------------------------------------------------------------------- /step-8-done/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'wines' 2 | 3 | include ':app' 4 | -------------------------------------------------------------------------------- /step-8-done/android/wines.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /step-8-done/index.android.js: -------------------------------------------------------------------------------- 1 | import { AppRegistry } from 'react-native'; 2 | import { App } from './src/app'; 3 | 4 | AppRegistry.registerComponent('wines', () => App); 5 | -------------------------------------------------------------------------------- /step-8-done/index.ios.js: -------------------------------------------------------------------------------- 1 | import { AppRegistry } from 'react-native'; 2 | import { App } from './src/app'; 3 | 4 | AppRegistry.registerComponent('wines', () => App); 5 | -------------------------------------------------------------------------------- /step-8-done/ios/wines/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (nonatomic, strong) UIWindow *window; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /step-8-done/ios/wines/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /step-8-done/ios/wines/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | #import "AppDelegate.h" 13 | 14 | int main(int argc, char * argv[]) { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /step-8-done/ios/winesTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /step-8-done/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wines", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node node_modules/react-native/local-cli/cli.js start", 7 | "install-android": "cd ./android && ./gradlew :app:installDebug", 8 | "run-adv": "$ANDROID_HOME/tools/emulator -netdelay none -netspeed full -avd reactnative", 9 | "start-android": "node node_modules/react-native/local-cli/cli.js run-android hot", 10 | "android-log": "adb logcat *:S ReactNative:V ReactNativeJS:V" 11 | }, 12 | "dependencies": { 13 | "moment": "2.12.0", 14 | "react": "0.14.8", 15 | "react-native": "0.24.0-rc2", 16 | "react-redux": "4.4.1", 17 | "redux": "3.3.1", 18 | "redux-thunk": "2.0.1" 19 | }, 20 | "devDependencies": { 21 | "eslint": "2.4.0", 22 | "eslint-plugin-react": "4.2.3" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /step-8-done/src/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react-native'; 2 | 3 | import { Provider } from 'react-redux'; 4 | import { createStore, applyMiddleware } from 'redux'; 5 | import thunk from 'redux-thunk'; 6 | import { app } from './reducers'; 7 | 8 | import { WineApp } from './components/wine-app'; 9 | 10 | const store = createStore(app, applyMiddleware(thunk)); 11 | 12 | export const App = React.createClass({ 13 | render() { 14 | return ( 15 | 16 | 17 | 18 | ); 19 | } 20 | }); 21 | -------------------------------------------------------------------------------- /step-8-done/src/components/button.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes, View, Text, StyleSheet } from 'react-native'; 2 | 3 | const styles = StyleSheet.create({ 4 | button: { 5 | borderColor: 'black', 6 | borderRadius: 4, 7 | borderWidth: 1, 8 | padding: 15, 9 | alignItems: 'center', 10 | justifyContent: 'center', 11 | alignItems: 'center', 12 | } 13 | }); 14 | 15 | export const Button = React.createClass({ 16 | propTypes: { 17 | action: PropTypes.func 18 | }, 19 | onAction() { 20 | (this.props.action || function() {})(); 21 | }, 22 | render() { 23 | return ( 24 | 25 | {this.props.title || this.props.children} 26 | 27 | ); 28 | } 29 | }); 30 | -------------------------------------------------------------------------------- /step-8-done/src/components/liked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8-done/src/components/liked.png -------------------------------------------------------------------------------- /step-8-done/src/components/loading.android.js: -------------------------------------------------------------------------------- 1 | import React, { 2 | PropTypes, 3 | ProgressBarAndroid, 4 | Text, 5 | View 6 | } from 'react-native'; 7 | import { styles } from './style'; 8 | 9 | export const Loading = React.createClass({ 10 | propTypes: { 11 | what: PropTypes.string 12 | }, 13 | render() { 14 | return( 15 | 16 | 17 | 18 | Loading {this.props.what} 19 | 20 | 24 | 25 | 26 | ); 27 | } 28 | }); 29 | -------------------------------------------------------------------------------- /step-8-done/src/components/loading.ios.js: -------------------------------------------------------------------------------- 1 | import React, { 2 | PropTypes, 3 | ActivityIndicatorIOS, 4 | Text, 5 | View 6 | } from 'react-native'; 7 | import { styles } from './style'; 8 | 9 | export const Loading = React.createClass({ 10 | propTypes: { 11 | what: PropTypes.string 12 | }, 13 | render() { 14 | return( 15 | 16 | 17 | 18 | Loading {this.props.what} 19 | 20 | 24 | 25 | 26 | ); 27 | } 28 | }); 29 | -------------------------------------------------------------------------------- /step-8-done/src/components/not-found.android.js: -------------------------------------------------------------------------------- 1 | import React, { 2 | View, 3 | Text 4 | } from 'react-native'; 5 | 6 | export const NotFound = React.createClass({ 7 | render() { 8 | return ( 9 | 10 | Il semble que vous n'êtes pas au bon endroit !!! 11 | 12 | ); 13 | } 14 | }); 15 | -------------------------------------------------------------------------------- /step-8-done/src/components/region-cell.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes, Text, TouchableHighlight, View } from 'react-native'; 2 | import { styles } from './style'; 3 | 4 | export const RegionCell = React.createClass({ 5 | propTypes: { 6 | onSelect: PropTypes.func, 7 | region: PropTypes.string 8 | }, 9 | render() { 10 | return ( 11 | 12 | 13 | 14 | {this.props.region} 15 | 16 | 17 | 18 | ); 19 | } 20 | }); 21 | -------------------------------------------------------------------------------- /step-8-done/src/components/unliked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8-done/src/components/unliked.png -------------------------------------------------------------------------------- /step-8-done/src/components/wine-app.ios.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes, NavigatorIOS } from 'react-native'; 2 | import { connect } from 'react-redux'; 3 | import { Regions } from './regions'; 4 | import { styles } from './style'; 5 | 6 | const mapStateToProps = (state) => { 7 | return { 8 | title: state.title, 9 | httpState: state.http.state, 10 | httpError: state.http.error 11 | }; 12 | } 13 | 14 | export const WineApp = connect(mapStateToProps)(React.createClass({ 15 | propTypes: { 16 | children: PropTypes.element, 17 | dispatch: PropTypes.func.isRequired, 18 | httpError: PropTypes.string, 19 | httpState: PropTypes.string, 20 | title: PropTypes.string.isRequired 21 | }, 22 | 23 | render() { 24 | return ( 25 | 31 | ); 32 | } 33 | 34 | })); 35 | -------------------------------------------------------------------------------- /step-8-done/src/components/wine-cell.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes, Text, TouchableHighlight, View } from 'react-native'; 2 | import { styles } from './style'; 3 | 4 | export const WineCell = React.createClass({ 5 | propTypes: { 6 | onSelect: PropTypes.func, 7 | wine: PropTypes.shape({ 8 | name: PropTypes.string 9 | }) 10 | }, 11 | render() { 12 | return ( 13 | 14 | 15 | 16 | {this.props.wine.name} 17 | 18 | 19 | 20 | ); 21 | } 22 | }); 23 | -------------------------------------------------------------------------------- /step-8-done/src/reducers/comments.js: -------------------------------------------------------------------------------- 1 | export const comments = (state = { count: 0 }, action) => { 2 | switch (action.type) { 3 | case 'ADD_COMMENT': 4 | return Object.assign({}, state, { count: state.count + action.increment }); 5 | case 'SET_COMMENTS': 6 | return Object.assign({}, state, { count: action.comments }); 7 | default: 8 | return state; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /step-8-done/src/reducers/http.js: -------------------------------------------------------------------------------- 1 | export const http = (state = { state: 'LOADED', error: undefined }, action) => { 2 | switch (action.type) { 3 | case 'LOADING': 4 | return Object.assign({}, state, { state: 'LOADING', error: undefined }); 5 | case 'LOADED': 6 | return Object.assign({}, state, { state: 'LOADED', error: undefined }); 7 | case 'ERROR': 8 | return Object.assign({}, state, { state: 'ERROR', error: action.error }); 9 | default: 10 | return state; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /step-8-done/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import { comments } from './comments'; 3 | import { likes } from './likes'; 4 | import { regions } from './regions'; 5 | import { wines, currentWine } from './wines'; 6 | import { title } from './title'; 7 | import { http } from './http'; 8 | 9 | /** 10 | * shape of the global state 11 | * 12 | * { 13 | * comments: { 14 | * count: 42 15 | * }, 16 | * likes: { 17 | * count: 42 18 | * }, 19 | * regions: { 20 | * lastUpdated: 0, 21 | * data: [...] 22 | * }, 23 | * wines: { 24 | * bordeaux: { 25 | * lastUpdated: 0, 26 | * data: [...] 27 | * }, 28 | * ... 29 | * }, 30 | * currentWine: { 31 | * wine: {...}, 32 | * liked: true, 33 | * comments: [...], 34 | * }, 35 | * title: 'Bordeaux', 36 | * http: { 37 | * state: 'LOADING', // LOADED, ERROR 38 | * error: '...' 39 | * } 40 | * } 41 | */ 42 | 43 | export const app = combineReducers({ 44 | comments, 45 | likes, 46 | regions, 47 | wines, 48 | currentWine, 49 | title, 50 | http 51 | }) 52 | -------------------------------------------------------------------------------- /step-8-done/src/reducers/likes.js: -------------------------------------------------------------------------------- 1 | export const likes = (state = { count: 0 }, action) => { 2 | switch (action.type) { 3 | case 'ADD_LIKE': 4 | return Object.assign({}, state, { count: state.count + action.increment }); 5 | case 'REMOVE_LIKE': 6 | return Object.assign({}, state, { count: state.count - action.decrement }); 7 | case 'SET_LIKES': 8 | return Object.assign({}, state, { count: action.likes }); 9 | default: 10 | return state; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /step-8-done/src/reducers/regions.js: -------------------------------------------------------------------------------- 1 | export const regions = (state = { data: [], lastUpdated: 0 }, action) => { 2 | switch (action.type) { 3 | case 'SET_REGIONS': 4 | return Object.assign({}, state, { data: action.regions }); 5 | case 'UPDATE_REGIONS_TIMESTAMP': 6 | return Object.assign({}, state, { lastUpdated: Date.now() }); 7 | default: 8 | return state; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /step-8-done/src/reducers/title.js: -------------------------------------------------------------------------------- 1 | export const title = (state = '', action) => { 2 | switch (action.type) { 3 | case 'SET_TITLE': 4 | return action.title; 5 | default: 6 | return state; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /step-8-done/src/reducers/wines.js: -------------------------------------------------------------------------------- 1 | export const wines = (state = {}, action) => { 2 | switch (action.type) { 3 | case 'SET_WINES': 4 | return Object.assign({}, state, { [action.region]: { lastUpdated: Date.now(), data: action.wines }}); 5 | case 'UPDATE_WINES_TIMESTAMP': 6 | return Object.assign({}, state, Object.assign({}, state[action.region], { lastUpdated: Date.now() })); 7 | default: 8 | return state; 9 | } 10 | } 11 | 12 | export const currentWine = (state = { wine: undefined, comments: [], liked: false }, action) => { 13 | switch (action.type) { 14 | case 'SET_CURRENT_WINE': 15 | return Object.assign({}, state, { wine: action.wine, liked: false }); 16 | case 'SET_CURRENT_COMMENTS': 17 | return Object.assign({}, state, { comments: action.comments }); 18 | case 'SET_CURRENT_LIKED': 19 | return Object.assign({}, state, { liked: action.liked }); 20 | default: 21 | return state; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /step-8/.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | webpack.config.js 3 | public 4 | README.md 5 | -------------------------------------------------------------------------------- /step-8/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | project.xcworkspace 24 | 25 | # Android/IJ 26 | # 27 | .idea 28 | .gradle 29 | local.properties 30 | 31 | # node.js 32 | # 33 | node_modules/ 34 | npm-debug.log 35 | -------------------------------------------------------------------------------- /step-8/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /step-8/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 11 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /step-8/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /step-8/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /step-8/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /step-8/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /step-8/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | wines 3 | 4 | -------------------------------------------------------------------------------- /step-8/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /step-8/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.3.1' 9 | 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | mavenLocal() 18 | jcenter() 19 | maven { 20 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 21 | url "$projectDir/../../node_modules/react-native/android" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /step-8/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | android.useDeprecatedNdk=true 21 | -------------------------------------------------------------------------------- /step-8/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /step-8/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip 6 | -------------------------------------------------------------------------------- /step-8/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'wines' 2 | 3 | include ':app' 4 | -------------------------------------------------------------------------------- /step-8/android/wines.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /step-8/index.android.js: -------------------------------------------------------------------------------- 1 | import { AppRegistry } from 'react-native'; 2 | import { App } from './src/app'; 3 | 4 | AppRegistry.registerComponent('wines', () => App); 5 | -------------------------------------------------------------------------------- /step-8/index.ios.js: -------------------------------------------------------------------------------- 1 | import { AppRegistry } from 'react-native'; 2 | import { App } from './src/app'; 3 | 4 | AppRegistry.registerComponent('wines', () => App); 5 | -------------------------------------------------------------------------------- /step-8/ios/wines/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (nonatomic, strong) UIWindow *window; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /step-8/ios/wines/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /step-8/ios/wines/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | #import "AppDelegate.h" 13 | 14 | int main(int argc, char * argv[]) { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /step-8/ios/winesTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /step-8/live-reload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8/live-reload.png -------------------------------------------------------------------------------- /step-8/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wines", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node node_modules/react-native/local-cli/cli.js start", 7 | "install-android": "cd ./android && ./gradlew :app:installDebug", 8 | "run-adv": "$ANDROID_HOME/tools/emulator -netdelay none -netspeed full -avd reactnative", 9 | "start-android": "node node_modules/react-native/local-cli/cli.js run-android hot", 10 | "android-log": "adb logcat *:S ReactNative:V ReactNativeJS:V" 11 | }, 12 | "dependencies": { 13 | "moment": "2.12.0", 14 | "react": "0.14.8", 15 | "react-native": "0.24.0-rc2", 16 | "react-redux": "4.4.1", 17 | "redux": "3.3.1", 18 | "redux-thunk": "2.0.1" 19 | }, 20 | "devDependencies": { 21 | "eslint": "2.4.0", 22 | "eslint-plugin-react": "4.2.3" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /step-8/reactnative-emulator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8/reactnative-emulator.png -------------------------------------------------------------------------------- /step-8/regions-android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8/regions-android.png -------------------------------------------------------------------------------- /step-8/regions-ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8/regions-ios.png -------------------------------------------------------------------------------- /step-8/src/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react-native'; 2 | import thunk from 'redux-thunk'; 3 | 4 | import { Provider } from 'react-redux'; 5 | import { app } from './reducers'; 6 | import { createStore, applyMiddleware } from 'redux'; 7 | 8 | import { WineApp } from './components/wine-app'; 9 | 10 | const store = createStore(app, applyMiddleware(thunk)); 11 | 12 | export const App = React.createClass({ 13 | render() { 14 | return ( 15 | 16 | 17 | 18 | ); 19 | } 20 | }); 21 | -------------------------------------------------------------------------------- /step-8/src/components/button.js: -------------------------------------------------------------------------------- 1 | import React, { PropTypes, View, Text, StyleSheet } from 'react-native'; 2 | 3 | const styles = StyleSheet.create({ 4 | button: { 5 | borderColor: 'black', 6 | borderRadius: 4, 7 | borderWidth: 1, 8 | padding: 15, 9 | alignItems: 'center', 10 | justifyContent: 'center' 11 | } 12 | }); 13 | 14 | export const Button = React.createClass({ 15 | propTypes: { 16 | action: PropTypes.func, 17 | style: PropTypes.object, 18 | title: PropTypes.string, 19 | titleStyle: PropTypes.object 20 | }, 21 | getDefaultProps() { 22 | return { 23 | action() {}, 24 | style: {}, 25 | titleStyle: {}, 26 | title: '' 27 | }; 28 | }, 29 | handleAction() { 30 | (this.props.action || function() {})(); 31 | }, 32 | render() { 33 | return ( 34 | 37 | 40 | {this.props.title || this.props.children} 41 | 42 | 43 | ); 44 | } 45 | }); 46 | -------------------------------------------------------------------------------- /step-8/src/components/comments.js: -------------------------------------------------------------------------------- 1 | /* eslint react/no-multi-comp: 0, react/jsx-max-props-per-line: 0 */ 2 | 3 | import React, { PropTypes, View, Text, TextInput } from 'react-native'; 4 | import moment from 'moment'; 5 | import { connect } from 'react-redux'; 6 | import { addComment, fetchComments, postComment } from '../actions'; 7 | import { styles } from './style'; 8 | import { Button } from './button'; 9 | 10 | const mapStateToProps = (state) => { 11 | return { 12 | comments: state.currentWine.comments 13 | }; 14 | } 15 | 16 | export const Comments = connect(mapStateToProps)(React.createClass({ 17 | getInitialState() { 18 | return { 19 | commentTitle: '', 20 | commentBody: '' 21 | }; 22 | }, 23 | 24 | handlePostComment() { 25 | const payload = { title: this.state.commentTitle, content: this.state.commentBody }; 26 | this.props.dispatch(postComment(this.props.wineId, payload)).then(() => { 27 | this.setState({ commentTitle: '', commentBody: '' }); 28 | }); 29 | }, 30 | 31 | render() { 32 | return ( 33 | comments 34 | ); 35 | } 36 | })); 37 | -------------------------------------------------------------------------------- /step-8/src/components/liked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8/src/components/liked.png -------------------------------------------------------------------------------- /step-8/src/components/loading.android.js: -------------------------------------------------------------------------------- 1 | import React, { 2 | PropTypes, 3 | ProgressBarAndroid, 4 | Text, 5 | View 6 | } from 'react-native'; 7 | import { styles } from './style'; 8 | 9 | export const Loading = React.createClass({ 10 | propTypes: { 11 | what: PropTypes.string 12 | }, 13 | render() { 14 | return( 15 | 16 | 17 | 18 | Loading {this.props.what} 19 | 20 | 24 | 25 | 26 | ); 27 | } 28 | }); 29 | -------------------------------------------------------------------------------- /step-8/src/components/loading.ios.js: -------------------------------------------------------------------------------- 1 | import React, { 2 | PropTypes, 3 | ActivityIndicatorIOS, 4 | Text, 5 | View 6 | } from 'react-native'; 7 | import { styles } from './style'; 8 | 9 | export const Loading = React.createClass({ 10 | propTypes: { 11 | what: PropTypes.string 12 | }, 13 | render() { 14 | return( 15 | 16 | 17 | 18 | Loading {this.props.what} 19 | 20 | 24 | 25 | 26 | ); 27 | } 28 | }); 29 | -------------------------------------------------------------------------------- /step-8/src/components/region-cell.js: -------------------------------------------------------------------------------- 1 | import React, { Text } from 'react-native'; 2 | 3 | export const RegionCell = React.createClass({ 4 | render() { 5 | return ( 6 | Item 7 | ); 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /step-8/src/components/regions.js: -------------------------------------------------------------------------------- 1 | /* eslint react/jsx-no-bind: 0, react/no-multi-comp: 0, react/jsx-closing-bracket-location: 0 */ 2 | 3 | import React from 'react-native'; 4 | 5 | import { connect } from 'react-redux'; 6 | 7 | const mapStateToProps = (state) => { 8 | return { 9 | regions: state.regions.data 10 | }; 11 | } 12 | 13 | export const Regions = connect(mapStateToProps)(React.createClass({ 14 | render() { 15 | return ( 16 | Items 17 | ); 18 | } 19 | })); 20 | -------------------------------------------------------------------------------- /step-8/src/components/unliked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8/src/components/unliked.png -------------------------------------------------------------------------------- /step-8/src/components/wine-app.android.js: -------------------------------------------------------------------------------- 1 | import React, { Navigator, BackAndroid } from 'react-native'; 2 | import { Loading } from './loading'; 3 | 4 | export const WineApp = React.createClass({ 5 | componentWillUnmount() { 6 | BackAndroid.removeEventListener('hardwareBackPress', this.handleBackButton); 7 | }, 8 | 9 | handleBackButton() { 10 | if (!this.isOnMainScreen) { 11 | this.navigator.pop(); 12 | return true; 13 | } 14 | return false; 15 | }, 16 | 17 | configureScene(route) { 18 | if (route.sceneConfig) { 19 | return route.sceneConfig; 20 | } 21 | return Navigator.SceneConfigs.FloatFromBottom; 22 | }, 23 | 24 | renderScene(route, nav) { 25 | if (!this.navigator) { 26 | this.navigator = nav; 27 | BackAndroid.addEventListener('hardwareBackPress', this.handleBackButton); 28 | } 29 | // return view for each route 30 | }, 31 | 32 | render() { 33 | return ( 34 | 35 | ); 36 | } 37 | }); 38 | -------------------------------------------------------------------------------- /step-8/src/components/wine-app.ios.js: -------------------------------------------------------------------------------- 1 | import React from 'react-native'; 2 | import { Loading } from './loading'; 3 | 4 | export const WineApp = React.createClass({ 5 | render() { 6 | return ( 7 | 8 | ); 9 | } 10 | }); 11 | -------------------------------------------------------------------------------- /step-8/src/components/wine-cell.js: -------------------------------------------------------------------------------- 1 | import React, { Text } from 'react-native'; 2 | 3 | export const WineCell = React.createClass({ 4 | render() { 5 | return ( 6 | Item 7 | ); 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /step-8/src/components/wine-list.js: -------------------------------------------------------------------------------- 1 | /* eslint react/jsx-no-bind: 0, react/no-multi-comp: 0, react/jsx-closing-bracket-location: 0 */ 2 | 3 | import React from 'react-native'; 4 | 5 | import { connect } from 'react-redux'; 6 | 7 | const mapStateToProps = (state) => { 8 | return { 9 | wines: state.wines 10 | }; 11 | } 12 | 13 | export const WineList = connect(mapStateToProps)(React.createClass({ 14 | render() { 15 | return ( 16 | Items 17 | ); 18 | } 19 | })); 20 | -------------------------------------------------------------------------------- /step-8/src/components/wine.js: -------------------------------------------------------------------------------- 1 | /* eslint react/no-multi-comp: 0, react/jsx-max-props-per-line: 0 */ 2 | 3 | import React, { PropTypes, Image, View, Text, ScrollView, TouchableWithoutFeedback } from 'react-native'; 4 | import { connect } from 'react-redux'; 5 | import { fetchWine, fetchWineLiked, setTitle, toggleWineLiked } from '../actions'; 6 | import { styles } from './style'; 7 | import { Comments } from './comments'; 8 | import { apiHost } from '../actions'; 9 | 10 | const mapStateToProps = (state) => { 11 | return { 12 | currentWine: state.currentWine.wine, 13 | liked: state.currentWine.liked 14 | }; 15 | } 16 | 17 | export const Wine = connect(mapStateToProps)(React.createClass({ 18 | componentDidMount() { 19 | this.props.dispatch(fetchWine(this.props.wine.id)).then(() => { 20 | this.props.dispatch(fetchWineLiked(this.props.wine.id)); 21 | }); 22 | }, 23 | 24 | handleToggleLike() { 25 | this.props.dispatch(toggleWineLiked(this.props.wine.id)); 26 | }, 27 | 28 | render() { 29 | const { wine, liked } = this.props; 30 | return ( 31 | Wine 32 | ); 33 | } 34 | })); 35 | -------------------------------------------------------------------------------- /step-8/src/reducers/comments.js: -------------------------------------------------------------------------------- 1 | export const comments = (state = { count: 0 }, action) => { 2 | switch (action.type) { 3 | case 'ADD_COMMENT': 4 | return Object.assign({}, state, { count: state.count + action.increment }); 5 | case 'SET_COMMENTS': 6 | return Object.assign({}, state, { count: action.comments }); 7 | default: 8 | return state; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /step-8/src/reducers/http.js: -------------------------------------------------------------------------------- 1 | export const http = (state = { state: 'LOADED', error: undefined }, action) => { 2 | switch (action.type) { 3 | case 'LOADING': 4 | return Object.assign({}, state, { state: 'LOADING', error: undefined }); 5 | case 'LOADED': 6 | return Object.assign({}, state, { state: 'LOADED', error: undefined }); 7 | case 'ERROR': 8 | return Object.assign({}, state, { state: 'ERROR', error: action.error }); 9 | default: 10 | return state; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /step-8/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | import { comments } from './comments'; 3 | import { likes } from './likes'; 4 | import { regions } from './regions'; 5 | import { wines, currentWine } from './wines'; 6 | import { title } from './title'; 7 | import { http } from './http'; 8 | 9 | /** 10 | * shape of the global state 11 | * 12 | * { 13 | * comments: { 14 | * count: 42 15 | * }, 16 | * likes: { 17 | * count: 42 18 | * }, 19 | * regions: { 20 | * lastUpdated: 0, 21 | * data: [...] 22 | * }, 23 | * wines: { 24 | * bordeaux: { 25 | * lastUpdated: 0, 26 | * data: [...] 27 | * }, 28 | * ... 29 | * }, 30 | * currentWine: { 31 | * wine: {...}, 32 | * liked: true, 33 | * comments: [...], 34 | * }, 35 | * title: 'Bordeaux', 36 | * http: { 37 | * state: 'LOADING', // LOADED, ERROR 38 | * error: '...' 39 | * } 40 | * } 41 | */ 42 | 43 | export const app = combineReducers({ 44 | comments, 45 | likes, 46 | regions, 47 | wines, 48 | currentWine, 49 | title, 50 | http 51 | }) 52 | -------------------------------------------------------------------------------- /step-8/src/reducers/likes.js: -------------------------------------------------------------------------------- 1 | export const likes = (state = { count: 0 }, action) => { 2 | switch (action.type) { 3 | case 'ADD_LIKE': 4 | return Object.assign({}, state, { count: state.count + action.increment }); 5 | case 'REMOVE_LIKE': 6 | return Object.assign({}, state, { count: state.count - action.decrement }); 7 | case 'SET_LIKES': 8 | return Object.assign({}, state, { count: action.likes }); 9 | default: 10 | return state; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /step-8/src/reducers/regions.js: -------------------------------------------------------------------------------- 1 | export const regions = (state = { data: [], lastUpdated: 0 }, action) => { 2 | switch (action.type) { 3 | case 'SET_REGIONS': 4 | return Object.assign({}, state, { data: action.regions }); 5 | case 'UPDATE_REGIONS_TIMESTAMP': 6 | return Object.assign({}, state, { lastUpdated: Date.now() }); 7 | default: 8 | return state; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /step-8/src/reducers/title.js: -------------------------------------------------------------------------------- 1 | export const title = (state = '', action) => { 2 | switch (action.type) { 3 | case 'SET_TITLE': 4 | return action.title; 5 | default: 6 | return state; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /step-8/src/reducers/wines.js: -------------------------------------------------------------------------------- 1 | export const wines = (state = {}, action) => { 2 | switch (action.type) { 3 | case 'SET_WINES': 4 | return Object.assign({}, state, { [action.region]: { lastUpdated: Date.now(), data: action.wines }}); 5 | case 'UPDATE_WINES_TIMESTAMP': 6 | return Object.assign({}, state, Object.assign({}, state[action.region], { lastUpdated: Date.now() })); 7 | default: 8 | return state; 9 | } 10 | } 11 | 12 | export const currentWine = (state = { wine: undefined, comments: [], liked: false }, action) => { 13 | switch (action.type) { 14 | case 'SET_CURRENT_WINE': 15 | return Object.assign({}, state, { wine: action.wine, liked: false }); 16 | case 'SET_CURRENT_COMMENTS': 17 | return Object.assign({}, state, { comments: action.comments }); 18 | case 'SET_CURRENT_LIKED': 19 | return Object.assign({}, state, { liked: action.liked }); 20 | default: 21 | return state; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /step-8/wine-liked-android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8/wine-liked-android.png -------------------------------------------------------------------------------- /step-8/wine-liked-ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8/wine-liked-ios.png -------------------------------------------------------------------------------- /step-8/wine-unliked-android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8/wine-unliked-android.png -------------------------------------------------------------------------------- /step-8/wine-unliked-ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8/wine-unliked-ios.png -------------------------------------------------------------------------------- /step-8/wines-android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8/wines-android.png -------------------------------------------------------------------------------- /step-8/wines-ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathieuancelin/react-workshop/59b3e809eaa4392f4f5c66c9bb5d0f460cff73ad/step-8/wines-ios.png -------------------------------------------------------------------------------- /test-all-done.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | APP_PATH=`pwd` 4 | 5 | cd "$APP_PATH/step-1-done" 6 | npm test 7 | cd "$APP_PATH/step-2-done" 8 | npm test 9 | cd "$APP_PATH/step-3-done" 10 | npm test 11 | cd "$APP_PATH/step-4-done" 12 | npm test 13 | cd "$APP_PATH/step-5-done" 14 | npm test 15 | cd "$APP_PATH/step-6-done" 16 | npm test 17 | cd "$APP_PATH/step-7" 18 | npm test 19 | 20 | cd "$APP_PATH" 21 | -------------------------------------------------------------------------------- /test-all-undone.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | APP_PATH=`pwd` 4 | 5 | cd "$APP_PATH/step-2" 6 | npm test 7 | cd "$APP_PATH/step-3" 8 | npm test 9 | cd "$APP_PATH/step-4" 10 | npm test 11 | cd "$APP_PATH/step-5" 12 | npm test 13 | cd "$APP_PATH/step-6" 14 | npm test 15 | cd "$APP_PATH/step-7" 16 | npm test 17 | 18 | cd "$APP_PATH" 19 | --------------------------------------------------------------------------------