Commit 1856a9e4 authored by Mori's avatar Mori

Initial commit

parents
### https://raw.github.com/github/gitignore/22a5eb3da72c0a224a179033e92722bdbf5a05ad/Ruby.gitignore
*.gem
*.rbc
/.config
/coverage/
/InstalledFiles
/pkg/
/spec/reports/
/spec/examples.txt
/test/tmp/
/test/version_tmp/
/tmp/
# Used by dotenv library to load environment variables.
# .env
## Specific to RubyMotion:
.dat*
.repl_history
build/
*.bridgesupport
build-iPhoneOS/
build-iPhoneSimulator/
## Specific to RubyMotion (use of CocoaPods):
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# vendor/Pods/
## Documentation cache and generated files:
/.yardoc/
/_yardoc/
/doc/
/rdoc/
## Environment normalization:
/.bundle/
/vendor/bundle
/lib/bundler/man/
# for a library or gem, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# Gemfile.lock
# .ruby-version
# .ruby-gemset
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
.rvmrc
### https://raw.github.com/github/gitignore/22a5eb3da72c0a224a179033e92722bdbf5a05ad/Global/MacOS.gitignore
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### https://raw.github.com/github/gitignore/22a5eb3da72c0a224a179033e92722bdbf5a05ad/Global/JetBrains.gitignore
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries
# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
# Gradle:
.idea/**/gradle.xml
.idea/**/libraries
# CMake
cmake-build-debug/
cmake-build-release/
# Mongo Explorer plugin:
.idea/**/mongoSettings.xml
## File-based project format:
*.iws
## Plugin-specific files:
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### https://raw.github.com/github/gitignore/22a5eb3da72c0a224a179033e92722bdbf5a05ad/Node.gitignore
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
# next.js build output
.next
### https://raw.github.com/github/gitignore/22a5eb3da72c0a224a179033e92722bdbf5a05ad/Global/VisualStudioCode.gitignore
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
# Private
.idea
# react-redux-typescript-firebase-auth
create-react-app with Redux and TypeScript and Firebase authentication
declare module '*.svg'
declare module '*.png'
declare module '*.jpg'
{
"name": "react-typescript-firebase-auth",
"version": "0.1.0",
"private": true,
"dependencies": {
"firebase": "^5.1.0",
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-redux": "^5.0.7",
"react-router-dom": "^4.3.1",
"react-scripts-ts": "2.16.0",
"recompose": "^0.27.1",
"redux": "^4.0.0"
},
"scripts": {
"start": "react-scripts-ts start",
"build": "react-scripts-ts build",
"test": "react-scripts-ts test --env=jsdom",
"eject": "react-scripts-ts eject",
"tslint": "tslint --project tsconfig.json",
"tslint:fix": "tslint --fix --project tsconfig.json"
},
"devDependencies": {
"@types/jest": "^23.1.1",
"@types/node": "^10.3.5",
"@types/react": "^16.4.1",
"@types/react-dom": "^16.0.6",
"@types/react-redux": "^6.0.3",
"@types/react-router-dom": "^4.2.7",
"@types/recompose": "^0.26.1",
"typescript": "^2.9.2"
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": "./index.html",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
import * as React from "react";
import { connect } from "react-redux";
import { compose } from "recompose";
import { PasswordChangeForm } from "../PasswordChange";
import { PasswordForgetForm } from "../PasswordForget/PasswordForgetForm";
import { withAuthorization } from "../Sessions/withAuthorization";
const AccountComponent = ({ authUser }: any) => (
<div>
<h1>Account: {authUser.email}</h1>
<PasswordForgetForm />
<PasswordChangeForm />
</div>
);
const mapStateToProps = (state: any) => ({
authUser: state.sessionState.authUser
});
const authCondition = (authUser: any) => !!authUser;
export const Account = compose(
withAuthorization(authCondition),
connect(mapStateToProps)
)(AccountComponent);
import * as React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import * as routes from "../../constants/routes";
import { firebase } from "../../firebase";
import { Account } from "../Account";
import { Home } from "../Home";
import { Landing } from "../Landing";
import { Navigation } from "../Navigation";
import { PasswordForget } from "../PasswordForget";
import { withAuthentication } from "../Sessions/withAuthentication";
import { SignIn } from "../SignIn";
import { SignUp } from "../SignUp";
class AppComponent extends React.Component {
constructor(props: any) {
super(props);
this.state = {
authUser: null
};
}
public componentDidMount() {
firebase.auth.onAuthStateChanged(authUser => {
authUser
? this.setState(() => ({ authUser }))
: this.setState(() => ({ authUser: null }));
});
}
public render() {
return (
<BrowserRouter>
<div>
<Navigation />
<hr />
<Switch>
<Route exact={true} path={routes.LANDING} component={Landing} />
<Route exact={true} path={routes.SIGN_UP} component={SignUp} />
<Route exact={true} path={routes.SIGN_IN} component={SignIn} />
<Route
exact={true}
path={routes.PASSWORD_FORGET}
component={PasswordForget}
/>
<Route exact={true} path={routes.HOME} component={Home} />
<Route exact={true} path={routes.ACCOUNT} component={Account} />
</Switch>
</div>
</BrowserRouter>
);
}
}
export const App = withAuthentication(AppComponent);
import * as React from "react";
interface InterfaceProps {
users?: any;
}
export class UserList extends React.Component<InterfaceProps, {}> {
constructor(props: any) {
super(props);
}
public render() {
const { users }: any = this.props;
return (
<div>
<h2>List of Usernames of Users</h2>
<p>(Saved on Sign Up in Firebase Database)</p>
{Object.keys(users).map(key => (
<div key={key}>{users[key].username}</div>
))}
</div>
);
}
}
import * as React from "react";
import * as ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { HashRouter } from "react-router-dom";
import store from "../../store";
import { Home } from "./index";
it("renders without crashing", () => {
const div = document.createElement("div");
ReactDOM.render(
<Provider store={store}>
<HashRouter>
<Home />
</HashRouter>
</Provider>,
div
);
ReactDOM.unmountComponentAtNode(div);
});
import * as React from "react";
import { connect } from "react-redux";
import { compose } from "recompose";
import { db } from "../../firebase";
import { withAuthorization } from "../Sessions/withAuthorization";
import { UserList } from "./UserList";
class HomeComponent extends React.Component {
public componentDidMount() {
const { onSetUsers }: any = this.props;
db.onceGetUsers().then(snapshot => onSetUsers(snapshot.val()));
}
public render() {
const { users }: any = this.props;
return (
<div>
<h1>Home</h1>
<p>The Home Page is accessible by every signed in user.</p>
{!!users && <UserList users={users} />}
</div>
);
}
}
const mapStateToProps = (state: any) => ({
users: state.userState.users
});
const mapDispatchToProps = (dispatch: any) => ({
onSetUsers: (users: any) => dispatch({ type: "USERS_SET", users })
});
const authCondition = (authUser: any) => !!authUser;
export const Home = compose(
withAuthorization(authCondition),
connect(
mapStateToProps,
mapDispatchToProps
)
)(HomeComponent);
import * as React from "react";
export const Landing = () => {
return (
<div>
<h2>Landing Page</h2>
</div>
);
};
import * as React from "react";
import { connect } from "react-redux";
import { Link } from "react-router-dom";
import * as routes from "../../constants/routes";
import { SignOutButton } from "../SignOut";
const NavigationComponent = ({ authUser }: any) => (
<div>{authUser ? <NavigationAuth /> : <NavigationNonAuth />}</div>
);
const NavigationAuth = () => (
<ul>
<li>
<Link to={routes.LANDING}>Landing</Link>
</li>
<li>
<Link to={routes.HOME}>Home</Link>
</li>
<li>
<Link to={routes.ACCOUNT}>Account</Link>
</li>
<li>
<SignOutButton />
</li>
</ul>
);
const NavigationNonAuth = () => (
<ul>
<li>
<Link to={routes.LANDING}>Landing</Link>
</li>
<li>
<Link to={routes.SIGN_IN}>Sign In</Link>
</li>
</ul>
);
const mapStateToProps = (state: any) => ({
authUser: state.sessionState.authUser
});
export const Navigation = connect(mapStateToProps)(NavigationComponent);
import * as React from "react";
import { auth } from "../../firebase";
interface InterfaceProps {
error?: any;
history?: any;
passwordOne?: string;
passwordTwo?: string;
}
interface InterfaceState {
error?: any;
passwordOne?: string;
passwordTwo?: string;
}
export class PasswordChangeForm extends React.Component<
InterfaceProps,
InterfaceState
> {
private static INITIAL_STATE = {
error: null,
passwordOne: "",
passwordTwo: ""
};
private static propKey(propertyName: string, value: string): object {
return { [propertyName]: value };
}
constructor(props: any) {
super(props);
this.state = { ...PasswordChangeForm.INITIAL_STATE };
}
public onSubmit = (event: any) => {
const { passwordOne }: any = this.state;
auth
.doPasswordUpdate(passwordOne)
.then(() => {
this.setState(() => ({ ...PasswordChangeForm.INITIAL_STATE }));
})
.catch(error => {
this.setState(PasswordChangeForm.propKey("error", error));
});
event.preventDefault();
};
public render() {
const { passwordOne, passwordTwo, error }: any = this.state;
const isInvalid = passwordOne !== passwordTwo || passwordOne === "";
return (
<form onSubmit={event => this.onSubmit(event)}>
<input
value={passwordOne}
onChange={event => this.setStateWithEvent(event, "passwordOne")}
type="password"
placeholder="New Password"
/>
<input
value={passwordTwo}
onChange={event => this.setStateWithEvent(event, "passwordTwo")}
type="password"
placeholder="Confirm New Password"
/>
<button disabled={isInvalid} type="submit">
Reset My Password
</button>
{error && <p>{error.message}</p>}
</form>
);
}
private setStateWithEvent(event: any, columnType: string): void {
this.setState(
PasswordChangeForm.propKey(columnType, (event.target as any).value)
);
}
}
import * as React from "react";
import { auth } from "../../firebase";
export class PasswordForgetForm extends React.Component {
private static INITIAL_STATE = {
email: "",
error: null
};
private static propKey(propertyName: string, value: string) {
return { [propertyName]: value };
}
constructor(props: any) {
super(props);
this.state = { ...PasswordForgetForm.INITIAL_STATE };
}
public onSubmit = (event: any) => {
const { email }: any = this.state;
auth
.doPasswordReset(email)
.then(() => {
this.setState(() => ({ ...PasswordForgetForm.INITIAL_STATE }));
})
.catch(error => {
this.setState(PasswordForgetForm.propKey("error", error));
});
event.preventDefault();
};
public render() {
const { email, error }: any = this.state;
const isInvalid = email === "";
return (
<form onSubmit={event => this.onSubmit(event)}>
<input
value={email}
onChange={event => this.setStateWithEvent(event, "email")}
type="text"
placeholder="Email Address"
/>
<button disabled={isInvalid} type="submit">
Reset My Password
</button>
{error && <p>{error.message}</p>}
</form>
);
}
private setStateWithEvent(event: any, columnType: string): void {
this.setState(
PasswordForgetForm.propKey(columnType, (event.target as any).value)
);
}
}
import * as React from "react";
import { Link } from "react-router-dom";
import { PasswordForgetForm } from "./PasswordForgetForm";
export const PasswordForget = () => (
<div>
<h1>PasswordForget</h1>
<PasswordForgetForm />
</div>
);
export const PasswordForgetLink = () => (
<p>
<Link to="/pw-forget">Forgot Password?</Link>
</p>
);
import * as React from "react";
import { connect } from "react-redux";
import { firebase } from "../../firebase";
interface InterfaceProps {
authUser?: any;
}
interface InterfaceState {
authUser?: any;
}
export const withAuthentication = (Component: any) => {
class WithAuthentication extends React.Component<
InterfaceProps,
InterfaceState
> {
public componentDidMount() {
const { onSetAuthUser }: any = this.props;
firebase.auth.onAuthStateChanged(authUser => {
authUser ? onSetAuthUser(authUser) : onSetAuthUser(null);
});
}
public render() {
return <Component />;
}
}
const mapDispatchToProps = (dispatch: any) => ({
onSetAuthUser: (authUser: any) =>
dispatch({ type: "AUTH_USER_SET", authUser })
});
return connect(
null,
mapDispatchToProps
)(WithAuthentication);
};
import * as React from "react";
import { connect } from "react-redux";
import { withRouter } from "react-router-dom";
import { compose } from "recompose";
import * as routes from "../../constants/routes";
import { firebase } from "../../firebase";
interface InterfaceProps {
history?: any;
authUser?: any;
}
export const withAuthorization = (condition: any) => (Component: any) => {
class WithAuthorization extends React.Component<InterfaceProps, any> {
public componentDidMount() {
firebase.auth.onAuthStateChanged(authUser => {
if (!condition(authUser)) {
this.props.history.push(routes.SIGN_IN);
}
});
}
public render() {
return this.props.authUser ? <Component /> : null;
}
}
const mapStateToProps = (state: any) => ({
authUser: state.sessionState.authUser
});
return compose(
withRouter,
connect(mapStateToProps)
)(WithAuthorization);
};
import * as React from "react";
import * as routes from "../../constants/routes";
import { auth } from "../../firebase";
interface InterfaceProps {
email?: string;
error?: any;
history?: any;
password?: string;
}
interface InterfaceState {
email: string;
error: any;
password: string;
}
export class SignInForm extends React.Component<
InterfaceProps,
InterfaceState
> {
private static INITIAL_STATE = {
email: "",
error: null,
password: ""
};
private static propKey(propertyName: string, value: any): object {
return { [propertyName]: value };
}
constructor(props: InterfaceProps) {
super(props);
this.state = { ...SignInForm.INITIAL_STATE };
}
public onSubmit = (event: any) => {
const { email, password } = this.state;
const { history } = this.props;
auth
.doSignInWithEmailAndPassword(email, password)
.then(() => {
this.setState(() => ({ ...SignInForm.INITIAL_STATE }));
history.push(routes.HOME);
})
.catch(error => {
this.setState(SignInForm.propKey("error", error));
});
event.preventDefault();
};
public render() {
const { email, password, error } = this.state;
const isInvalid = password === "" || email === "";
return (
<form onSubmit={event => this.onSubmit(event)}>
<input
value={email}
onChange={event => this.setStateWithEvent(event, "email")}
type="text"
placeholder="Email Address"
/>
<input
value={password}
onChange={event => this.setStateWithEvent(event, "password")}
type="password"
placeholder="Password"
/>
<button disabled={isInvalid} type="submit">
Sign In
</button>
{error && <p>{error.message}</p>}
</form>
);
}
private setStateWithEvent(event: any, columnType: string): void {
this.setState(SignInForm.propKey(columnType, (event.target as any).value));
}
}
import * as React from "react";
import { withRouter } from "react-router-dom";
import { PasswordForgetLink } from "../PasswordForget";
import { SignUpLink } from "../SignUp";
import { SignInForm } from "./SignInForm";
const SignInComponent = ({ history }: { [key: string]: any }) => (
<div>
<h1>SignIn</h1>
<SignInForm history={history} />
<SignUpLink />
<PasswordForgetLink />
</div>
);
export const SignIn = withRouter(SignInComponent);
import * as React from "react";
import { auth } from "../../firebase";
export const SignOutButton = () => (
<button type="button" onClick={auth.doSignOut}>
Sign Out
</button>
);
import * as React from "react";
import * as routes from "../../constants/routes";
import { auth, db } from "../../firebase";
interface InterfaceProps {
email?: string;
error?: any;
history?: any;
passwordOne?: string;
passwordTwo?: string;
username?: string;
}
interface InterfaceState {
email: string;
error: any;
passwordOne: string;
passwordTwo: string;
username: string;
}
export class SignUpForm extends React.Component<
InterfaceProps,
InterfaceState
> {
private static INITIAL_STATE = {
email: "",
error: null,
passwordOne: "",
passwordTwo: "",
username: ""
};
private static propKey(propertyName: string, value: any): object {
return { [propertyName]: value };
}
constructor(props: InterfaceProps) {
super(props);
this.state = { ...SignUpForm.INITIAL_STATE };
}
public onSubmit(event: any) {
event.preventDefault();
const { email, passwordOne, username } = this.state;
const { history } = this.props;
auth
.doCreateUserWithEmailAndPassword(email, passwordOne)
.then((authUser: any) => {
// Create a user in your own accessible Firebase Database too
db.doCreateUser(authUser.user.uid, username, email)
.then(() => {
this.setState(() => ({ ...SignUpForm.INITIAL_STATE }));
history.push(routes.HOME);
})
.catch(error => {
this.setState(SignUpForm.propKey("error", error));
});
})
.catch(error => {
this.setState(SignUpForm.propKey("error", error));
});
}
public render() {
const { username, email, passwordOne, passwordTwo, error } = this.state;
const isInvalid =
passwordOne !== passwordTwo ||
passwordOne === "" ||
email === "" ||
username === "";
return (
<form onSubmit={(event) => this.onSubmit(event)}>
<input
value={username}
onChange={event => this.setStateWithEvent(event, "username")}
type="text"
placeholder="Full Name"
/>
<input
value={email}
onChange={event => this.setStateWithEvent(event, "email")}
type="text"
placeholder="Email Address"
/>
<input
value={passwordOne}
onChange={event => this.setStateWithEvent(event, "passwordOne")}
type="password"
placeholder="Password"
/>
<input
value={passwordTwo}
onChange={event => this.setStateWithEvent(event, "passwordTwo")}
type="password"
placeholder="Confirm Password"
/>
<button disabled={isInvalid} type="submit">
Sign Up
</button>
{error && <p>{error.message}</p>}
</form>
);
}
private setStateWithEvent(event: any, columnType: string) {
this.setState(SignUpForm.propKey(columnType, (event.target as any).value));
}
}
import * as React from "react";
import { Link, withRouter } from "react-router-dom";
import * as routes from "../../constants/routes";
import { SignUpForm } from "./SingUpForm";
const SignUpComponent = () => (
<div>
<h1>SignUp</h1>
<SignUpForm />
</div>
);
export const SignUpLink = () => (
<p>
Don't have an account? <Link to={routes.SIGN_UP}>Sign Up</Link>
</p>
);
export const SignUp = withRouter(SignUpComponent);
export const SIGN_UP = "/signup";
export const SIGN_IN = "/signin";
export const LANDING = "/";
export const HOME = "/home";
export const ACCOUNT = "/account";
export const PASSWORD_FORGET = "/pw-forget";
import { auth } from "./firebase";
// Sign Up
export const doCreateUserWithEmailAndPassword = (
email: string,
password: string
) => auth.createUserWithEmailAndPassword(email, password);
// Sign In
export const doSignInWithEmailAndPassword = (email: string, password: string) =>
auth.signInWithEmailAndPassword(email, password);
// Sign out
export const doSignOut = () => auth.signOut();
// Password Reset
export const doPasswordReset = (email: string) =>
auth.sendPasswordResetEmail(email);
// Password Change
export const doPasswordUpdate = async (password: string) => {
if (auth.currentUser) {
await auth.currentUser.updatePassword(password);
}
throw Error("No auth.currentUser!");
};
import { db } from "./firebase";
// User API
export const doCreateUser = (id: string, username: string, email: string) =>
db.ref(`users/${id}`).set({
email,
username
});
export const onceGetUsers = () => db.ref("users").once("value");
import * as firebase from "firebase/app";
import "firebase/auth";
import "firebase/database";
const config = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_AUTH_DOMAIN",
databaseURL: "YOUR_DATABASE_URL",
messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
projectId: "YOUR PROJECT_ID",
storageBucket: "YOUR_STORAGE_BUCKET"
};
if (!firebase.apps.length) {
firebase.initializeApp(config);
}
export const auth = firebase.auth();
export const db = firebase.database();
import * as auth from "./auth";
import * as db from "./db";
import * as firebase from "./firebase";
export { auth, db, firebase };
body {
margin: 0;
padding: 0;
font-family: sans-serif;
}
import * as React from "react";
import * as ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { App } from "./components/App";
import "./index.css";
import registerServiceWorker from "./registerServiceWorker";
import store from "./store";
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
registerServiceWorker();
import { combineReducers } from "redux";
import { sessionReducer } from "./session";
import { userReducer } from "./user";
export const rootReducer = combineReducers({
sessionState: sessionReducer,
userState: userReducer
});
const INITIAL_STATE = {
authUser: null
};
const applySetAuthUser = (state: any, action: any) => ({
...state,
authUser: action.authUser
});
export function sessionReducer(state = INITIAL_STATE, action: any) {
switch (action.type) {
case "AUTH_USER_SET": {
return applySetAuthUser(state, action);
}
default:
return state;
}
}
const INITIAL_STATE = {
users: {}
};
const applySetUsers = (state: any, action: any) => ({
...state,
users: action.users
});
export function userReducer(state = INITIAL_STATE, action: any) {
switch (action.type) {
case "USERS_SET": {
return applySetUsers(state, action);
}
default:
return state;
}
}
// tslint:disable:no-console
// 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.toString()
);
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: string) {
navigator.serviceWorker
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
if (installingWorker) {
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: string) {
// 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();
});
}
}
import { createStore } from "redux";
import { rootReducer } from "../reducers";
const store = createStore(rootReducer);
export default store;
{
"compilerOptions": {
"baseUrl": ".",
"outDir": "build/dist",
"module": "esnext",
"target": "es5",
"lib": ["es6", "dom"],
"sourceMap": true,
"allowJs": true,
"jsx": "react",
"moduleResolution": "node",
"rootDir": "src",
"forceConsistentCasingInFileNames": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"noUnusedLocals": true
},
"exclude": [
"node_modules",
"build",
"scripts",
"acceptance-tests",
"webpack",
"jest",
"src/setupTests.ts"
]
}
{
"extends": "./tsconfig.json"
}
\ No newline at end of file
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs"
}
}
\ No newline at end of file
{
"extends": ["tslint:recommended", "tslint-react", "tslint-config-prettier"],
"rules": {
"jsx-no-lambda": false
},
"linterOptions": {
"exclude": ["config/**/*.js", "node_modules/**/*.ts"]
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment