From d11f8ca97a54fb72533023c8093e1596d7439487 Mon Sep 17 00:00:00 2001 From: Andy Mikulski Date: Mon, 26 Feb 2018 13:56:47 -0700 Subject: [PATCH] Flow, prettier, Login page --- .flowconfig | 2 + .prettierrc | 6 ++ .vscode/settings.json | 3 + package.json | 11 +-- src/console/LoginPage.js | 58 +++++++++++++ src/console/index.js | 92 +++++++++++++++++---- src/console/registerServiceWorker.js | 117 --------------------------- src/index.js | 2 - yarn.lock | 19 ++++- 9 files changed, 169 insertions(+), 141 deletions(-) create mode 100644 .flowconfig create mode 100644 .prettierrc create mode 100644 .vscode/settings.json create mode 100644 src/console/LoginPage.js delete mode 100644 src/console/registerServiceWorker.js diff --git a/.flowconfig b/.flowconfig new file mode 100644 index 0000000..567238d --- /dev/null +++ b/.flowconfig @@ -0,0 +1,2 @@ +[options] +module.name_mapper='^normandy\/\(.*\)$' -> '/src/normandy/\1' \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..7e8946e --- /dev/null +++ b/.prettierrc @@ -0,0 +1,6 @@ +{ + "parser": "flow", + "loglevel": "warn", + "singleQuote": true, + "trailingComma": "all" +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..db871f2 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.hover": false +} \ No newline at end of file diff --git a/package.json b/package.json index 4c996b2..3736846 100644 --- a/package.json +++ b/package.json @@ -26,16 +26,13 @@ "build": "react-app-rewired build", "test": "react-app-rewired test --env=jsdom", "eject": "react-scripts eject", - "precommit": "lint-staged" - }, - "lint-staged": { - "*.{js,json,css,md,less}": ["prettier --write", "git add"] + "lint:flow": "flow --quiet", + "lint:prettier": "prettier **/**/*.js --write", + "lint": "yarn run lint:flow && yarn run lint:prettier" }, "devDependencies": { "babel-plugin-import": "^1.6.5", - "babel-plugin-transform-decorators-legacy": "^1.3.4", - "husky": "^0.14.3", - "lint-staged": "^7.0.0", + "flow-bin": "^0.66.0", "prettier": "^1.10.2", "react-app-rewire-less": "^2.1.0", "react-app-rewired": "^1.4.1" diff --git a/src/console/LoginPage.js b/src/console/LoginPage.js new file mode 100644 index 0000000..78b3ae0 --- /dev/null +++ b/src/console/LoginPage.js @@ -0,0 +1,58 @@ +/* @flow */ +import React, { Component } from 'react'; +import { withRouter } from 'react-router-dom'; + +type Props = { + onAuth: Function, + history: ReactRouterHistory, + location: any, +}; +type State = {}; + +class LoginPage extends Component { + state = {}; + + onSubmit = evt => { + evt.preventDefault(); + const form = evt.target; + + let data = {}; + let i = form.length - 1; + let input; + while (i >= 0) { + input = form[i]; + if (input.name) { + data[input.name] = input.value; + } + i -= 1; + } + + this.props.onAuth( + data.user, + Math.random() + .toString(36) + .slice(2), + ); + + // Route may have a `next` query param. If so, redirect to that page. + let query = this.props.location.search || '/'; + query = query.replace('?next=', ''); + + this.props.history.push(query); + }; + + render() { + return ( +
+
+ + + + +
+
+ ); + } +} + +export default withRouter(LoginPage); diff --git a/src/console/index.js b/src/console/index.js index 57e5fa6..f4c3cac 100644 --- a/src/console/index.js +++ b/src/console/index.js @@ -1,11 +1,50 @@ -import React, { Component } from "react"; -import logo from "./logo.svg"; -import "./App.css"; -import Normandy from "normandy/index.js"; -import { BrowserRouter, Link } from "react-router-dom"; -import { Route } from "react-router"; +/* @flow */ + +import React, { Component } from 'react'; +import logo from './logo.svg'; +import './App.css'; +import LoginPage from './LoginPage'; +import { BrowserRouter, Link } from 'react-router-dom'; +import { Route, Redirect } from 'react-router'; + +type AppProps = {}; +type AppState = { + authToken: ?string, + username: ?string, +}; + +const Homepage = props => ( +
+

Welcome home!

+ {props.authToken ? ( +

+ Go to the Normandy page. +

+ ) : ( +

+ Go to the login page. +

+ )} +
+); + +const MockNormandy = props => ( +
Normandy with auth token {props.authToken}
+); + +class App extends Component { + state = { + authToken: null, + username: null, + }; + + onUserLogin = (username: string, authToken: string) => { + this.setState({ + username, + authToken, + }); + }; -class App extends Component { render() { return ( @@ -14,17 +53,42 @@ class App extends Component { logo

Welcome to Delivery Console

+ {this.state.username && ( +
You are logged in as {this.state.username}.
+ )}
+ {/* Homepage */} ( -
-

Delivery Console

- Normandy -
- )} + component={() => } + /> + + {/* Login */} + + this.state.username ? ( + + ) : ( + + ) + } + /> + + {/* Normandy App */} + + this.state.username ? ( + + ) : ( + + ) + } /> -
diff --git a/src/console/registerServiceWorker.js b/src/console/registerServiceWorker.js deleted file mode 100644 index a3e6c0c..0000000 --- a/src/console/registerServiceWorker.js +++ /dev/null @@ -1,117 +0,0 @@ -// In production, we register a service worker to serve assets from local cache. - -// This lets the app load faster on subsequent visits in production, and gives -// it offline capabilities. However, it also means that developers (and users) -// will only see deployed updates on the "N+1" visit to a page, since previously -// cached resources are updated in the background. - -// To learn more about the benefits of this model, read https://goo.gl/KwvDNy. -// This link also includes instructions on opting out of this behavior. - -const isLocalhost = Boolean( - window.location.hostname === 'localhost' || - // [::1] is the IPv6 localhost address. - window.location.hostname === '[::1]' || - // 127.0.0.1/8 is considered localhost for IPv4. - window.location.hostname.match( - /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ - ) -); - -export default function register() { - if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { - // The URL constructor is available in all browsers that support SW. - const publicUrl = new URL(process.env.PUBLIC_URL, window.location); - if (publicUrl.origin !== window.location.origin) { - // Our service worker won't work if PUBLIC_URL is on a different origin - // from what our page is served on. This might happen if a CDN is used to - // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374 - return; - } - - window.addEventListener('load', () => { - const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; - - if (isLocalhost) { - // This is running on localhost. Lets check if a service worker still exists or not. - checkValidServiceWorker(swUrl); - - // Add some additional logging to localhost, pointing developers to the - // service worker/PWA documentation. - navigator.serviceWorker.ready.then(() => { - console.log( - 'This web app is being served cache-first by a service ' + - 'worker. To learn more, visit https://goo.gl/SC7cgQ' - ); - }); - } else { - // Is not local host. Just register service worker - registerValidSW(swUrl); - } - }); - } -} - -function registerValidSW(swUrl) { - navigator.serviceWorker - .register(swUrl) - .then(registration => { - registration.onupdatefound = () => { - const installingWorker = registration.installing; - installingWorker.onstatechange = () => { - if (installingWorker.state === 'installed') { - if (navigator.serviceWorker.controller) { - // At this point, the old content will have been purged and - // the fresh content will have been added to the cache. - // It's the perfect time to display a "New content is - // available; please refresh." message in your web app. - console.log('New content is available; please refresh.'); - } else { - // At this point, everything has been precached. - // It's the perfect time to display a - // "Content is cached for offline use." message. - console.log('Content is cached for offline use.'); - } - } - }; - }; - }) - .catch(error => { - console.error('Error during service worker registration:', error); - }); -} - -function checkValidServiceWorker(swUrl) { - // Check if the service worker can be found. If it can't reload the page. - fetch(swUrl) - .then(response => { - // Ensure service worker exists, and that we really are getting a JS file. - if ( - response.status === 404 || - response.headers.get('content-type').indexOf('javascript') === -1 - ) { - // No service worker found. Probably a different app. Reload the page. - navigator.serviceWorker.ready.then(registration => { - registration.unregister().then(() => { - window.location.reload(); - }); - }); - } else { - // Service worker found. Proceed as normal. - registerValidSW(swUrl); - } - }) - .catch(() => { - console.log( - 'No internet connection found. App is running in offline mode.' - ); - }); -} - -export function unregister() { - if ('serviceWorker' in navigator) { - navigator.serviceWorker.ready.then(registration => { - registration.unregister(); - }); - } -} diff --git a/src/index.js b/src/index.js index fd75a1b..dfc7ab5 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,5 @@ import React from "react"; import ReactDOM from "react-dom"; import DevConsoleApp from "./console"; -// import registerServiceWorker from './registerServiceWorker'; ReactDOM.render(, document.getElementById("root")); -// registerServiceWorker(); diff --git a/yarn.lock b/yarn.lock index ea5e7db..8aecb61 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2930,7 +2930,13 @@ fb-watchman@^2.0.0: dependencies: bser "^2.0.0" -fbjs@^0.8.1, fbjs@^0.8.15, fbjs@^0.8.16, fbjs@^0.8.9: +fbemitter@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/fbemitter/-/fbemitter-2.1.1.tgz#523e14fdaf5248805bb02f62efc33be703f51865" + dependencies: + fbjs "^0.8.4" + +fbjs@^0.8.0, fbjs@^0.8.1, fbjs@^0.8.15, fbjs@^0.8.16, fbjs@^0.8.4, fbjs@^0.8.9: version "0.8.16" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" dependencies: @@ -3061,6 +3067,17 @@ flatten@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" +flow-bin@^0.66.0: + version "0.66.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.66.0.tgz#a96dde7015dc3343fd552a7b4963c02be705ca26" + +flux@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/flux/-/flux-3.1.3.tgz#d23bed515a79a22d933ab53ab4ada19d05b2f08a" + dependencies: + fbemitter "^2.0.0" + fbjs "^0.8.0" + for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"