From 41ff359ca0d78ad79ce23909d7a8d89669536bc5 Mon Sep 17 00:00:00 2001 From: Boimer Date: Tue, 15 Jan 2019 16:56:45 -0800 Subject: [PATCH] Converting to TypeScript --- assets/package.json | 20 ++++- assets/src/{App.test.js => App.test.tsx} | 0 assets/src/{App.js => App.tsx} | 23 ++++-- assets/src/Routes.js | 29 -------- assets/src/Routes.tsx | 34 +++++++++ .../common/{AddToCart.js => AddToCart.tsx} | 17 ++++- .../{AppliedRoute.js => PropsRoute.tsx} | 3 +- ...endations.js => FriendRecommendations.tsx} | 16 +++- .../{FriendThumb.js => FriendThumb.tsx} | 4 +- assets/src/common/hero/{Hero.js => Hero.tsx} | 0 .../src/common/loaderButton/LoaderButton.css | 9 --- .../src/common/loaderButton/LoaderButton.js | 20 ----- .../{StarRating.js => StarRating.tsx} | 6 +- assets/src/{config.js => config.ts} | 0 assets/src/{index.js => index.tsx} | 0 ...ProductRow.js => BestSellerProductRow.tsx} | 26 ++++++- .../{BestSellers.js => BestSellers.tsx} | 13 +++- .../{BestSellersBar.js => BestSellersBar.tsx} | 0 .../{CartProductRow.js => CartProductRow.tsx} | 31 ++++++-- .../{ShoppingCart.js => ShoppingCart.tsx} | 21 ++++-- ...CategoryGallery.js => CategoryGallery.tsx} | 16 +++- ...GalleryBook.js => CategoryGalleryBook.tsx} | 7 +- ...eryTeaser.js => CategoryGalleryTeaser.tsx} | 14 +++- .../{CategoryView.js => CategoryView.tsx} | 6 +- .../{CategoryNavBar.js => CategoryNavBar.tsx} | 2 - .../{categories.js => categories.ts} | 0 .../checkout/{Checkout.js => Checkout.tsx} | 0 ...CheckoutConfirm.js => CheckoutConfirm.tsx} | 0 .../{CheckoutForm.js => CheckoutForm.tsx} | 34 +++++++-- .../{FriendsBought.js => FriendsBought.tsx} | 17 ++++- .../friends/{ProductRow.js => ProductRow.tsx} | 17 ++++- .../notFound/{NotFound.js => NotFound.tsx} | 0 .../{PastPurchases.js => PastPurchases.tsx} | 25 +++++-- ...dProductRow.js => PurchasedProductRow.tsx} | 26 +++++-- .../{SearchGallery.js => SearchGallery.tsx} | 18 ++++- .../search/{SearchView.js => SearchView.tsx} | 6 +- .../searchBar/{SearchBar.js => SearchBar.tsx} | 18 +++-- .../src/modules/signup/{Home.js => Home.tsx} | 12 ++- .../modules/signup/{Login.js => Login.tsx} | 46 ++++++++---- .../modules/signup/{Signup.js => Signup.tsx} | 74 ++++++++++++------- assets/src/react-app-env.d.ts | 1 + ...viceWorker.js => registerServiceWorker.ts} | 40 +++++----- assets/src/types/aws-amplify-react.d.ts | 1 + assets/tsconfig.json | 28 +++++++ 44 files changed, 469 insertions(+), 211 deletions(-) rename assets/src/{App.test.js => App.test.tsx} (100%) rename assets/src/{App.js => App.tsx} (93%) delete mode 100644 assets/src/Routes.js create mode 100644 assets/src/Routes.tsx rename assets/src/common/{AddToCart.js => AddToCart.tsx} (84%) rename assets/src/common/{AppliedRoute.js => PropsRoute.tsx} (75%) rename assets/src/common/friendRecommendations/{FriendRecommendations.js => FriendRecommendations.tsx} (74%) rename assets/src/common/friendRecommendations/{FriendThumb.js => FriendThumb.tsx} (87%) rename assets/src/common/hero/{Hero.js => Hero.tsx} (100%) delete mode 100644 assets/src/common/loaderButton/LoaderButton.css delete mode 100644 assets/src/common/loaderButton/LoaderButton.js rename assets/src/common/starRating/{StarRating.js => StarRating.tsx} (85%) rename assets/src/{config.js => config.ts} (100%) rename assets/src/{index.js => index.tsx} (100%) rename assets/src/modules/bestSellers/{BestSellerProductRow.js => BestSellerProductRow.tsx} (76%) rename assets/src/modules/bestSellers/{BestSellers.js => BestSellers.tsx} (83%) rename assets/src/modules/bestSellers/bestSellersBar/{BestSellersBar.js => BestSellersBar.tsx} (100%) rename assets/src/modules/cart/{CartProductRow.js => CartProductRow.tsx} (77%) rename assets/src/modules/cart/{ShoppingCart.js => ShoppingCart.tsx} (79%) rename assets/src/modules/category/{CategoryGallery.js => CategoryGallery.tsx} (74%) rename assets/src/modules/category/{CategoryGalleryBook.js => CategoryGalleryBook.tsx} (81%) rename assets/src/modules/category/{CategoryGalleryTeaser.js => CategoryGalleryTeaser.tsx} (73%) rename assets/src/modules/category/{CategoryView.js => CategoryView.tsx} (93%) rename assets/src/modules/category/categoryNavBar/{CategoryNavBar.js => CategoryNavBar.tsx} (99%) rename assets/src/modules/category/categoryNavBar/{categories.js => categories.ts} (100%) rename assets/src/modules/checkout/{Checkout.js => Checkout.tsx} (100%) rename assets/src/modules/checkout/{CheckoutConfirm.js => CheckoutConfirm.tsx} (100%) rename assets/src/modules/checkout/checkoutForm/{CheckoutForm.js => CheckoutForm.tsx} (80%) rename assets/src/modules/friends/{FriendsBought.js => FriendsBought.tsx} (66%) rename assets/src/modules/friends/{ProductRow.js => ProductRow.tsx} (79%) rename assets/src/modules/notFound/{NotFound.js => NotFound.tsx} (100%) rename assets/src/modules/pastPurchases/{PastPurchases.js => PastPurchases.tsx} (80%) rename assets/src/modules/pastPurchases/{PurchasedProductRow.js => PurchasedProductRow.tsx} (69%) rename assets/src/modules/search/{SearchGallery.js => SearchGallery.tsx} (80%) rename assets/src/modules/search/{SearchView.js => SearchView.tsx} (77%) rename assets/src/modules/search/searchBar/{SearchBar.js => SearchBar.tsx} (76%) rename assets/src/modules/signup/{Home.js => Home.tsx} (97%) rename assets/src/modules/signup/{Login.js => Login.tsx} (63%) rename assets/src/modules/signup/{Signup.js => Signup.tsx} (66%) create mode 100644 assets/src/react-app-env.d.ts rename assets/src/{registerServiceWorker.js => registerServiceWorker.ts} (76%) create mode 100644 assets/src/types/aws-amplify-react.d.ts create mode 100644 assets/tsconfig.json diff --git a/assets/package.json b/assets/package.json index 4c09dc08b..584842a1c 100644 --- a/assets/package.json +++ b/assets/package.json @@ -1,8 +1,15 @@ { - "name": "marvin-2.0", + "name": "aws-bookstore-demo-app", "version": "0.1.0", "private": true, "dependencies": { + "@types/jest": "^23.3.10", + "@types/node": "^10.12.12", + "@types/react": "^16.7.12", + "@types/react-bootstrap": "^0.32.15", + "@types/react-dom": "^16.0.11", + "@types/react-router-bootstrap": "^0.24.5", + "@types/react-router-dom": "^4.3.1", "aws-amplify": "^1.0.10", "bootstrap": "^3.3.7", "react": "^16.5.0", @@ -10,7 +17,8 @@ "react-dom": "^16.5.0", "react-router-bootstrap": "^0.24.4", "react-router-dom": "^4.3.1", - "react-scripts": "1.1.5" + "react-scripts": "^2.1.0", + "typescript": "^3.2.1" }, "scripts": { "start": "react-scripts start", @@ -18,5 +26,11 @@ "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" }, - "devDependencies": {} + "devDependencies": {}, + "browserslist": [ + ">0.2%", + "not dead", + "not ie <= 11", + "not op_mini all" + ] } diff --git a/assets/src/App.test.js b/assets/src/App.test.tsx similarity index 100% rename from assets/src/App.test.js rename to assets/src/App.test.tsx diff --git a/assets/src/App.js b/assets/src/App.tsx similarity index 93% rename from assets/src/App.js rename to assets/src/App.tsx index 04129c0e6..869a375a0 100644 --- a/assets/src/App.js +++ b/assets/src/App.tsx @@ -4,12 +4,21 @@ import { LinkContainer } from "react-router-bootstrap"; import { Link, withRouter } from "react-router-dom"; import { Nav, Navbar, NavItem } from "react-bootstrap"; import "./App.css"; -import Routes from "./Routes"; +import { Routes } from "./Routes"; const bookstoreIcon = "data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjMycHgiIGhlaWdodD0iMzJweCIgdmlld0JveD0iMCAwIDMzNS4wOCAzMzUuMDc5IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAzMzUuMDggMzM1LjA3OTsiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8Zz4KCTxnPgoJCTxwYXRoIGQ9Ik0zMTEuMTc1LDExNS43NzVjLTEuMzU1LTEwLjE4Ni0xLjU0Ni0yNy43Myw3LjkxNS0zMy42MjFjMC4xNjktMC4xMDgsMC4yOTUtMC4yNjQsMC40NDMtMC4zOTggICAgYzcuNzM1LTIuNDc0LDEzLjA4OC01Ljk0Niw4Ljg4Ni0xMC42MThsLTExNC4xMDItMzQuMzhMMjkuNTYsNjIuNDQ1YzAsMC0yMS4xNTcsMy4wMjQtMTkuMjY3LDM1Ljg5NCAgICBjMS4wMjYsMTcuODksNi42MzcsMjYuNjc2LDExLjU0NCwzMWwtMTUuMTYxLDQuNTY5Yy00LjIwOCw0LjY3MiwxLjE0NCw4LjE0NSw4Ljg4LDEwLjYxNWMwLjE0NywwLjEzOCwwLjI3MSwwLjI5MywwLjQ0MywwLjQwMSAgICBjOS40NTUsNS44OTYsOS4yNzMsMjMuNDM4LDcuOTEzLDMzLjYyNmMtMzMuOTY3LDkuNjQ1LTIxLjc3NCwxMi43ODgtMjEuNzc0LDEyLjc4OGw3LjQ1MSwxLjgwMyAgICBjLTUuMjQxLDQuNzM2LTEwLjQ0NiwxMy43MTctOS40NzEsMzAuNzVjMS44OTEsMzIuODY0LDE5LjI2OSwzNS4xMzIsMTkuMjY5LDM1LjEzMmwxMjAuOTA0LDM5LjI5OGwxODIuNDktNDQuMjAyICAgIGMwLDAsMTIuMTk3LTMuMTQ4LTIxLjc3OS0xMi43OTRjLTEuMzY2LTEwLjE3Mi0xLjU1Ni0yNy43MTIsNy45MjEtMzMuNjIzYzAuMTc0LTAuMTA1LDAuMzAxLTAuMjY0LDAuNDQyLTAuMzk2ICAgIGM3LjczNi0yLjQ3NCwxMy4wODQtNS45NDMsOC44ODEtMTAuNjE1bC03LjkzMi0yLjM5NWM1LjI5LTMuMTksMTMuMjM2LTExLjUyNywxNC40ODEtMzMuMTgzICAgIGMwLjg1OS0xNC44OTYtMy4wMjctMjMuNjItNy41MjUtMjguNzU2bDE1LjY3OC0zLjc5NEMzMzIuOTQ5LDEyOC41NjksMzQ1LjE0NiwxMjUuNDIxLDMxMS4xNzUsMTE1Ljc3NXogTTE1OC41MzMsMTE1LjM1NCAgICBsMzAuNjg4LTYuMzA3bDEwMy43MDgtMjEuMzEybDE1LjQ1MS0zLjE3OGMtNC45MzcsOS4wMzYtNC43MywyMS40MDItMy45MTMsMjkuMzVjMC4xNzksMS43OTgsMC4zODUsMy40NCwwLjU4NSw0LjY4OCAgICBMMjg4LjE0LDEyMi44bC0xMzAuODk3LDMyLjU2M0wxNTguNTMzLDExNS4zNTR6IE0yNi43MSwxNDcuMzM3bDE1LjQ0OSwzLjE3OGw5OS41OTcsMjAuNDc0bDguNzAxLDEuNzgybDAsMGwwLDBsMjYuMDkzLDUuMzYzICAgIGwxLjI4Nyw0MC4wMUw0My4zMDMsMTg0LjY3M2wtMTMuMjYzLTMuMjk2YzAuMTk1LTEuMjUsMC40MDEtMi44OSwwLjU4OC00LjY5M0MzMS40NCwxNjguNzQyLDMxLjY1MSwxNTYuMzczLDI2LjcxLDE0Ny4zMzd6ICAgICBNMjAuNzA4LDk2Ljc1N2MtMC4xODctOC43NDMsMS4zNzEtMTUuMDY2LDQuNTItMTguMjhjMi4wMDQtMi4wNTIsNC4zNjktMi40NzksNS45OTEtMi40NzljMC44NTcsMCwxLjQ3NCwwLjExOSwxLjUxNiwwLjExOSAgICBsNzkuNjA3LDI1Ljk1M2wzOS43MTcsMTIuOTQ5bC0xLjMwMyw0MC4yODlMMzkuMzM0LDEyNC4wN2wtNS44OC0xLjY0N2MtMC4yMTYtMC4wNjEtMC41MDktMC4xMDMtMC43MzUtMC4xMTMgICAgQzMyLjI2LDEyMi4yNzcsMjEuMjQ0LDEyMS4yNjMsMjAuNzA4LDk2Ljc1N3ogTTE0MC41NzksMjgwLjg2NkwyMy4yOCwyNDcuOThjLTAuMjE3LTAuMDYzLTAuNTA3LTAuMTA1LTAuNzMzLTAuMTE2ICAgIGMtMC40NjctMC4wMzEtMTEuNDg4LTEuMDQ0LTEyLjAyMS0yNS41NDRjLTAuMTktOC43NTQsMS4zNzYtMTUuMDcxLDQuNTE5LTE4LjI4OGMyLjAwOS0yLjA1Miw0LjM3NS0yLjQ3OSw1Ljk5NC0yLjQ3OSAgICBjMC44NTksMCwxLjQ3NCwwLjExNSwxLjUxOSwwLjExNWMwLDAsMC4wMDUsMCwwLDBsMTE5LjMxNiwzOC45MDhMMTQwLjU3OSwyODAuODY2eiBNMjk0LjI4NCwyMzkuNDU5ICAgIGMwLjE4NSwxLjgwNCwwLjM5MSwzLjQ0MywwLjU5MSw0LjY5M2wtMTQ3LjgxMiwzNi43NzFsMS4yOTItNDAuMDFsMzEuNjAxLTYuNDk3bDQuNjY3LDEuMTI5bDE3LjQ5Mi01LjY4NWw4MC42MzEtMTYuNTY5ICAgIGwxNS40NTctMy4xOEMyOTMuMjYxLDIxOS4xNDYsMjkzLjQ2NiwyMzEuNTE3LDI5NC4yODQsMjM5LjQ1OXogTTMwMi40MjYsMTg1LjA4NGMtMC4yNjksMC4wMDYtMC41MzgsMC4wNDItMC43OTEsMC4xMjIgICAgbC0xMS4xNDgsMy4xMjFsLTEwNi4xNDgsMjkuNzY0bC0xLjI5OC00MC4yODlsMzQuODI2LTExLjM1OWw4NC4zMjctMjcuNTAxYzAuMDExLTAuMDA1LDQuNDM2LTAuOTg4LDcuNjg0LDIuMzE1ICAgIGMzLjE0NCwzLjIxNCw0LjcwNCw5LjUzNyw0LjUyLDE4LjI4QzMxMy44NDgsMTg0LjAzNSwzMDIuODI3LDE4NS4wNTMsMzAyLjQyNiwxODUuMDg0eiIgZmlsbD0iI2Y2OTgyNyIvPgoJPC9nPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+Cjwvc3ZnPgo="; -class App extends Component { - constructor(props) { +interface AppProps { + history: any; +} + +interface AppState { + isAuthenticated: boolean; + isAuthenticating: boolean; +} + +class App extends Component { + constructor(props: AppProps) { super(props); this.state = { @@ -35,11 +44,11 @@ class App extends Component { this.setState({ isAuthenticating: false }); } - userHasAuthenticated = authenticated => { + userHasAuthenticated = (authenticated: boolean) => { this.setState({ isAuthenticated: authenticated }); } - handleLogout = async (event) => { + handleLogout = async () => { await Auth.signOut(); this.userHasAuthenticated(false); @@ -100,10 +109,10 @@ class App extends Component { - + ); } } -export default withRouter(App); \ No newline at end of file +export default withRouter(App as any); \ No newline at end of file diff --git a/assets/src/Routes.js b/assets/src/Routes.js deleted file mode 100644 index a18cf6251..000000000 --- a/assets/src/Routes.js +++ /dev/null @@ -1,29 +0,0 @@ -import React from "react"; -import { Route, Switch } from "react-router-dom"; -import AppliedRoute from "./common/AppliedRoute"; -import Checkout from "./modules/checkout/Checkout"; -import CheckoutConfirm from "./modules/checkout/CheckoutConfirm"; -import Home from "./modules/signup/Home"; -import Login from "./modules/signup/Login"; -import NotFound from "./modules/notFound/NotFound"; -import Signup from "./modules/signup/Signup"; -import CategoryView from "./modules/category/CategoryView"; -import ShoppingCart from "./modules/cart/ShoppingCart"; -import PastPurchases from "./modules/pastPurchases/PastPurchases"; -import BestSellers from "./modules/bestSellers/BestSellers"; -import SearchView from "./modules/search/SearchView" - -export default ({ childProps }) => - - - - - - - - - - - - - ; \ No newline at end of file diff --git a/assets/src/Routes.tsx b/assets/src/Routes.tsx new file mode 100644 index 000000000..148ed0dd1 --- /dev/null +++ b/assets/src/Routes.tsx @@ -0,0 +1,34 @@ +import React from "react"; +import { Route, Switch } from "react-router-dom"; +import Checkout from "./modules/checkout/Checkout"; +import CheckoutConfirm from "./modules/checkout/CheckoutConfirm"; +import Home from "./modules/signup/Home"; +import Login from "./modules/signup/Login"; +import NotFound from "./modules/notFound/NotFound"; +import Signup from "./modules/signup/Signup"; +import CategoryView from "./modules/category/CategoryView"; +import ShoppingCart from "./modules/cart/ShoppingCart"; +import PastPurchases from "./modules/pastPurchases/PastPurchases"; +import BestSellers from "./modules/bestSellers/BestSellers"; +import SearchView from "./modules/search/SearchView"; +import PropsRoute from "./common/PropsRoute"; + +interface RouteProps { + isAuthenticated: boolean; + userHasAuthenticated: (authenticated: boolean) => void; +} + +export const Routes: React.SFC = (childProps) => + + + + + + + + + + + + + ; \ No newline at end of file diff --git a/assets/src/common/AddToCart.js b/assets/src/common/AddToCart.tsx similarity index 84% rename from assets/src/common/AddToCart.js rename to assets/src/common/AddToCart.tsx index b4966da37..a92432320 100644 --- a/assets/src/common/AddToCart.js +++ b/assets/src/common/AddToCart.tsx @@ -3,8 +3,19 @@ import { API } from 'aws-amplify'; import { Redirect } from 'react-router'; import { Glyphicon } from 'react-bootstrap'; -class AddToCart extends React.Component { - constructor(props) { +interface AddToCartProps { + bookId: string; + price: number; + variant?: string; +} + +interface AddToCartState { + loading: boolean; + toCart: boolean; +} + +class AddToCart extends React.Component { + constructor(props: AddToCartProps) { super(props); this.state = { @@ -15,7 +26,7 @@ class AddToCart extends React.Component { onAddToCart = async () => { this.setState({ loading: true }); - const bookInCart = await API.get("cart", `/cart/${this.props.bookId}`); + const bookInCart = await API.get("cart", `/cart/${this.props.bookId}`, null); // if the book already exists in the cart, increase the quantity if (bookInCart) { diff --git a/assets/src/common/AppliedRoute.js b/assets/src/common/PropsRoute.tsx similarity index 75% rename from assets/src/common/AppliedRoute.js rename to assets/src/common/PropsRoute.tsx index 362a69f47..457232e95 100644 --- a/assets/src/common/AppliedRoute.js +++ b/assets/src/common/PropsRoute.tsx @@ -1,5 +1,6 @@ import React from "react"; -import { Route } from "react-router-dom"; +import { Route } from "react-router"; +//@ts-ignore export default ({ component: C, props: cProps, ...rest }) => } />; \ No newline at end of file diff --git a/assets/src/common/friendRecommendations/FriendRecommendations.js b/assets/src/common/friendRecommendations/FriendRecommendations.tsx similarity index 74% rename from assets/src/common/friendRecommendations/FriendRecommendations.js rename to assets/src/common/friendRecommendations/FriendRecommendations.tsx index 5c4c231a8..dc59fddb1 100644 --- a/assets/src/common/friendRecommendations/FriendRecommendations.js +++ b/assets/src/common/friendRecommendations/FriendRecommendations.tsx @@ -2,8 +2,16 @@ import { API } from 'aws-amplify'; import React from 'react'; import { FriendThumb } from './FriendThumb'; -class FriendRecommendations extends React.Component { - constructor(props) { +interface FriendRecommendationsProps { + bookId: string; +} + +interface FriendRecommendationsState { + friends: any[]; +} + +class FriendRecommendations extends React.Component { + constructor(props: FriendRecommendationsProps) { super(props); this.state = { @@ -12,7 +20,7 @@ class FriendRecommendations extends React.Component { } getFriends = () => { - return API.get("recommendations", `/recommendations/${this.props.bookId}`); + return API.get("recommendations", `/recommendations/${this.props.bookId}`, null); } async componentDidMount() { @@ -36,7 +44,7 @@ class FriendRecommendations extends React.Component {
Friends who bought this book

- {friends.slice(0, 3).map(friend => )} + {friends.slice(0, 3).map((friend: any) => )} {numFriendsPurchased > 3 && {` +${numFriendsPurchased - 3} ${(numFriendsPurchased - 3) > 1 ? "others" : "other"}`}}

diff --git a/assets/src/common/friendRecommendations/FriendThumb.js b/assets/src/common/friendRecommendations/FriendThumb.tsx similarity index 87% rename from assets/src/common/friendRecommendations/FriendThumb.js rename to assets/src/common/friendRecommendations/FriendThumb.tsx index 5810ab2a2..259dd80b9 100644 --- a/assets/src/common/friendRecommendations/FriendThumb.js +++ b/assets/src/common/friendRecommendations/FriendThumb.tsx @@ -10,7 +10,9 @@ import Sarah from "../../images/avatars/Sarah.png"; const friends = [Brenda, Erin, Jacob, Jeff, Jennifer, John, Sarah]; -export class FriendThumb extends React.Component { +interface FriendThumbProps {} + +export class FriendThumb extends React.Component { render() { const randomFriend = friends[Math.floor(Math.random() * friends.length)]; return ( diff --git a/assets/src/common/hero/Hero.js b/assets/src/common/hero/Hero.tsx similarity index 100% rename from assets/src/common/hero/Hero.js rename to assets/src/common/hero/Hero.tsx diff --git a/assets/src/common/loaderButton/LoaderButton.css b/assets/src/common/loaderButton/LoaderButton.css deleted file mode 100644 index a597babfb..000000000 --- a/assets/src/common/loaderButton/LoaderButton.css +++ /dev/null @@ -1,9 +0,0 @@ -.spinning.glyphicon { - margin-right: 7px; - top: 2px; - animation: spin 1s infinite linear; -} -@keyframes spin { - from { transform: scale(1) rotate(0deg); } - to { transform: scale(1) rotate(360deg); } -} \ No newline at end of file diff --git a/assets/src/common/loaderButton/LoaderButton.js b/assets/src/common/loaderButton/LoaderButton.js deleted file mode 100644 index 8cbdd6eae..000000000 --- a/assets/src/common/loaderButton/LoaderButton.js +++ /dev/null @@ -1,20 +0,0 @@ -import React from "react"; -import { Button, Glyphicon } from "react-bootstrap"; -import "./LoaderButton.css"; - -export default ({ - isLoading, - text, - loadingText, - className = "", - disabled = false, - ...props -}) => - ; \ No newline at end of file diff --git a/assets/src/common/starRating/StarRating.js b/assets/src/common/starRating/StarRating.tsx similarity index 85% rename from assets/src/common/starRating/StarRating.js rename to assets/src/common/starRating/StarRating.tsx index d38b3c59f..897b9db65 100644 --- a/assets/src/common/starRating/StarRating.js +++ b/assets/src/common/starRating/StarRating.tsx @@ -2,7 +2,11 @@ import React from 'react'; import { Glyphicon } from 'react-bootstrap'; import "./starRating.css"; -class StarRating extends React.Component { +interface StarRatingProps { + stars: number +} + +class StarRating extends React.Component { render() { return ( diff --git a/assets/src/config.js b/assets/src/config.ts similarity index 100% rename from assets/src/config.js rename to assets/src/config.ts diff --git a/assets/src/index.js b/assets/src/index.tsx similarity index 100% rename from assets/src/index.js rename to assets/src/index.tsx diff --git a/assets/src/modules/bestSellers/BestSellerProductRow.js b/assets/src/modules/bestSellers/BestSellerProductRow.tsx similarity index 76% rename from assets/src/modules/bestSellers/BestSellerProductRow.js rename to assets/src/modules/bestSellers/BestSellerProductRow.tsx index fec85d475..30e1eb7fd 100644 --- a/assets/src/modules/bestSellers/BestSellerProductRow.js +++ b/assets/src/modules/bestSellers/BestSellerProductRow.tsx @@ -6,12 +6,30 @@ import FriendRecommendations from "../../common/friendRecommendations/FriendReco import StarRating from "../../common/starRating/StarRating"; import "../../common/styles/productRow.css"; -export class ProductRow extends React.Component { - constructor(props) { +interface ProductRowProps { + bookId: string; +} + +export interface Book { + id: string; + cover: string; + price: number; + category: string; + name: string; + rating: number; + author: string; +} + +interface ProductRowState { + book: Book | undefined; +} + +export class ProductRow extends React.Component { + constructor(props: ProductRowProps) { super(props); this.state = { - book: null, + book: undefined, }; } @@ -25,7 +43,7 @@ export class ProductRow extends React.Component { } getBook() { - return API.get("books", `/books/${this.props.bookId}`); + return API.get("books", `/books/${this.props.bookId}`, null); } render() { diff --git a/assets/src/modules/bestSellers/BestSellers.js b/assets/src/modules/bestSellers/BestSellers.tsx similarity index 83% rename from assets/src/modules/bestSellers/BestSellers.js rename to assets/src/modules/bestSellers/BestSellers.tsx index b42c4ac8a..3228cdf88 100644 --- a/assets/src/modules/bestSellers/BestSellers.js +++ b/assets/src/modules/bestSellers/BestSellers.tsx @@ -5,8 +5,15 @@ import BestSellerProductRow from "./BestSellerProductRow"; import { CategoryNavBar } from "../category/categoryNavBar/CategoryNavBar"; import { SearchBar } from "../search/searchBar/SearchBar"; -export default class BestSellers extends React.Component { - constructor(props) { +interface BestSellersProps {} + +interface BestSellersState { + isLoading: boolean; + books: { bookId: any; }[]; +} + +export default class BestSellers extends React.Component { + constructor(props: BestSellersProps) { super(props); this.state = { @@ -18,7 +25,7 @@ export default class BestSellers extends React.Component { async componentDidMount() { try { const books = []; - const bestSellers = await API.get("bestsellers", "/bestsellers"); + const bestSellers = await API.get("bestsellers", "/bestsellers", null); // Map the elasticache results to a book object for (var i = 0; i < bestSellers.length; i++) { diff --git a/assets/src/modules/bestSellers/bestSellersBar/BestSellersBar.js b/assets/src/modules/bestSellers/bestSellersBar/BestSellersBar.tsx similarity index 100% rename from assets/src/modules/bestSellers/bestSellersBar/BestSellersBar.js rename to assets/src/modules/bestSellers/bestSellersBar/BestSellersBar.tsx diff --git a/assets/src/modules/cart/CartProductRow.js b/assets/src/modules/cart/CartProductRow.tsx similarity index 77% rename from assets/src/modules/cart/CartProductRow.js rename to assets/src/modules/cart/CartProductRow.tsx index dc3c04279..cce0b6aba 100644 --- a/assets/src/modules/cart/CartProductRow.js +++ b/assets/src/modules/cart/CartProductRow.tsx @@ -4,13 +4,30 @@ import { API } from "aws-amplify"; import StarRating from "../../common/starRating/StarRating"; import FriendRecommendations from "../../common/friendRecommendations/FriendRecommendations"; import { Glyphicon } from "react-bootstrap"; +import { Book } from "../bestSellers/BestSellerProductRow"; -export class CartProductRow extends React.Component { - constructor(props) { +export interface Order { + bookId: string; + quantity: number; + price: number +} + +interface CartProductRowProps { + order: Order; + calculateTotal: () => void; +} + +interface CartProductRowState { + book: Book | undefined; + removeLoading: boolean; +} + +export class CartProductRow extends React.Component { + constructor(props: CartProductRowProps) { super(props); this.state = { - book: null, + book: undefined, removeLoading: false }; } @@ -24,8 +41,8 @@ export class CartProductRow extends React.Component { } } - getBook(order) { - return API.get("books", `/books/${order.bookId}`); + getBook(order: Order) { + return API.get("books", `/books/${order.bookId}`, null); } onRemove = async () => { @@ -39,7 +56,7 @@ export class CartProductRow extends React.Component { this.props.calculateTotal(); } - onQuantityUpdated = async (event) => { + onQuantityUpdated = async (event: any) => { await API.put("cart", "/cart", { body: { bookId: this.props.order.bookId, @@ -72,7 +89,7 @@ export class CartProductRow extends React.Component {
- +
{this.state.recommendations.slice(0,5).map(recommendation => - + )}
); diff --git a/assets/src/modules/friends/ProductRow.js b/assets/src/modules/friends/ProductRow.tsx similarity index 79% rename from assets/src/modules/friends/ProductRow.js rename to assets/src/modules/friends/ProductRow.tsx index 33dd12ef9..65de9a513 100644 --- a/assets/src/modules/friends/ProductRow.js +++ b/assets/src/modules/friends/ProductRow.tsx @@ -4,18 +4,27 @@ import StarRating from "../../common/starRating/StarRating"; import { API } from "aws-amplify"; import AddToCart from "../../common/AddToCart"; import FriendRecommendations from "../../common/friendRecommendations/FriendRecommendations"; +import { Book } from "../bestSellers/BestSellerProductRow"; -export class ProductRow extends React.Component { - constructor(props) { +interface ProductRowProps { + bookId: string; +} + +interface ProductRowState { + book: Book | undefined; +} + +export class ProductRow extends React.Component { + constructor(props: ProductRowProps) { super(props); this.state = { - book: null, + book: undefined, }; } componentDidMount() { - API.get("books", `/books/${this.props.bookId}`) + API.get("books", `/books/${this.props.bookId}`, null) .then(response => this.setState({ book: response })) .catch(error => alert(error)); } diff --git a/assets/src/modules/notFound/NotFound.js b/assets/src/modules/notFound/NotFound.tsx similarity index 100% rename from assets/src/modules/notFound/NotFound.js rename to assets/src/modules/notFound/NotFound.tsx diff --git a/assets/src/modules/pastPurchases/PastPurchases.js b/assets/src/modules/pastPurchases/PastPurchases.tsx similarity index 80% rename from assets/src/modules/pastPurchases/PastPurchases.js rename to assets/src/modules/pastPurchases/PastPurchases.tsx index e7f7057ab..2877b1015 100644 --- a/assets/src/modules/pastPurchases/PastPurchases.js +++ b/assets/src/modules/pastPurchases/PastPurchases.tsx @@ -6,9 +6,24 @@ import { PurchasedProductRow } from "./PurchasedProductRow"; import { Auth, API } from "aws-amplify"; import bestSellers from "../../images/bestSellers.png"; import yourshoppingcart from "../../images/yourshoppingcart.png"; +import { Order } from "../cart/CartProductRow"; -export default class PastPurchases extends Component { - constructor(props) { +interface PastPurchasesProps {} + +interface Purchases { + orderDate: number; + orderId: string; + books: Order[]; +} + +interface PastPurchasesState { + userInfo: any; // FIXME + isLoading: boolean; + orders: Purchases[]; +} + +export default class PastPurchases extends Component { + constructor(props: PastPurchasesProps) { super(props); this.state = { @@ -34,10 +49,10 @@ export default class PastPurchases extends Component { } listOrders() { - return API.get("orders", "/orders"); + return API.get("orders", "/orders", null); } - getPrettyDate = (orderDate) => { + getPrettyDate = (orderDate: number) => { const date = new Date(orderDate); return `${date.getMonth()}/${date.getDate()}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes() < 10 ? '0' : ''}${date.getMinutes()}` } @@ -59,7 +74,7 @@ export default class PastPurchases extends Component { .map(order =>

{`Order date: ${this.getPrettyDate(order.orderDate)}`}

- {order.books.map((book) => )} + {order.books.map((book) => )}
) } diff --git a/assets/src/modules/pastPurchases/PurchasedProductRow.js b/assets/src/modules/pastPurchases/PurchasedProductRow.tsx similarity index 69% rename from assets/src/modules/pastPurchases/PurchasedProductRow.js rename to assets/src/modules/pastPurchases/PurchasedProductRow.tsx index d52ca52ec..fb8d960ce 100644 --- a/assets/src/modules/pastPurchases/PurchasedProductRow.js +++ b/assets/src/modules/pastPurchases/PurchasedProductRow.tsx @@ -4,27 +4,37 @@ import StarRating from "../../common/starRating/StarRating"; import { API } from "aws-amplify"; import AddToCart from "../../common/AddToCart"; import FriendRecommendations from "../../common/friendRecommendations/FriendRecommendations"; +import { Book } from "../bestSellers/BestSellerProductRow"; +import { Order } from "../cart/CartProductRow"; -export class PurchasedProductRow extends React.Component { - constructor(props) { +interface PurchasedProductRowProps { + order: Order; +} + +interface PurchasedProductRowState { + book: Book | undefined; +} + +export class PurchasedProductRow extends React.Component { + constructor(props: PurchasedProductRowProps) { super(props); this.state = { - book: null + book: undefined }; } async componentDidMount() { try { - const book = await this.getBook(this.props.book); + const book = await this.getBook(this.props.order); this.setState({ book }); } catch (e) { alert(e); } } - getBook(order) { - return API.get("books", `/books/${order.bookId}`); + getBook(order: Order) { + return API.get("books", `/books/${order.bookId}`, null); } render() { @@ -49,11 +59,11 @@ export class PurchasedProductRow extends React.Component {

{this.state.book.name}
- {`${this.props.book.quantity} @ ${this.state.book.price}`} + {`${this.props.order.quantity} @ ${this.state.book.price}`}

{this.state.book.category} - +
Rating diff --git a/assets/src/modules/search/SearchGallery.js b/assets/src/modules/search/SearchGallery.tsx similarity index 80% rename from assets/src/modules/search/SearchGallery.js rename to assets/src/modules/search/SearchGallery.tsx index ac171b9a1..0b4eb1205 100644 --- a/assets/src/modules/search/SearchGallery.js +++ b/assets/src/modules/search/SearchGallery.tsx @@ -2,9 +2,19 @@ import React from "react"; import "../../common/styles/gallery.css"; import { API } from "aws-amplify"; import CategoryGalleryBook from "../category/CategoryGalleryBook"; +import { Book } from "../bestSellers/BestSellerProductRow"; -export class SearchGallery extends React.Component { - constructor(props) { +interface SearchGalleryProps { + match: any; +} + +interface SearchGalleryState { + isLoading: boolean; + books: Book[]; +} + +export class SearchGallery extends React.Component { + constructor(props: SearchGalleryProps) { super(props); this.state = { @@ -43,7 +53,7 @@ export class SearchGallery extends React.Component { } searchBooks() { - return API.get("search", `/search?q=${this.props.match.params.id}`); + return API.get("search", `/search?q=${this.props.match.params.id}`, null); } render() { @@ -54,7 +64,7 @@ export class SearchGallery extends React.Component {

Search results

- {this.state.books.map(book => )} + {this.state.books.map(book => )}
diff --git a/assets/src/modules/search/SearchView.js b/assets/src/modules/search/SearchView.tsx similarity index 77% rename from assets/src/modules/search/SearchView.js rename to assets/src/modules/search/SearchView.tsx index fab5fb7fe..b5c204ba7 100644 --- a/assets/src/modules/search/SearchView.js +++ b/assets/src/modules/search/SearchView.tsx @@ -3,7 +3,11 @@ import { CategoryNavBar } from "../category/categoryNavBar/CategoryNavBar"; import { SearchBar } from "./searchBar/SearchBar"; import { SearchGallery } from "./SearchGallery"; -export default class SearchView extends Component { +interface SearchViewProps { + match: any; +} + +export default class SearchView extends Component { render() { return (
diff --git a/assets/src/modules/search/searchBar/SearchBar.js b/assets/src/modules/search/searchBar/SearchBar.tsx similarity index 76% rename from assets/src/modules/search/searchBar/SearchBar.js rename to assets/src/modules/search/searchBar/SearchBar.tsx index 65526f5f8..bf483b6c0 100644 --- a/assets/src/modules/search/searchBar/SearchBar.js +++ b/assets/src/modules/search/searchBar/SearchBar.tsx @@ -2,18 +2,26 @@ import React from "react"; import "./searchBar.css"; import { Redirect } from "react-router"; -export class SearchBar extends React.Component { - constructor(props) { +interface SearchBarProps {} + +interface SearchBarState { + redirect: string | undefined; + value: string; +} + +export class SearchBar extends React.Component { + constructor(props: SearchBarProps) { super(props); this.state = { - redirect: null, + redirect: undefined, value: "" }; } - handleChange = (e) => { - this.setState({ value: e.target.value }); + handleChange = (event: React.ChangeEvent) => { + const target = event.currentTarget as HTMLInputElement; + this.setState({ value: target.value }); } onSearch = () => { diff --git a/assets/src/modules/signup/Home.js b/assets/src/modules/signup/Home.tsx similarity index 97% rename from assets/src/modules/signup/Home.js rename to assets/src/modules/signup/Home.tsx index f0fcb771a..8b66ac0e7 100644 --- a/assets/src/modules/signup/Home.js +++ b/assets/src/modules/signup/Home.tsx @@ -12,8 +12,16 @@ import { FriendsBought } from "../friends/FriendsBought"; import { LinkContainer } from "react-router-bootstrap"; import "./home.css"; -export default class Home extends Component { - constructor(props) { +interface HomeProps { + isAuthenticated: boolean; +} + +interface HomeState { + isLoading: boolean; +} + +export default class Home extends Component { + constructor(props: HomeProps) { super(props); this.state = { diff --git a/assets/src/modules/signup/Login.js b/assets/src/modules/signup/Login.tsx similarity index 63% rename from assets/src/modules/signup/Login.js rename to assets/src/modules/signup/Login.tsx index 4cbd53271..794ddc21b 100644 --- a/assets/src/modules/signup/Login.js +++ b/assets/src/modules/signup/Login.tsx @@ -6,8 +6,22 @@ import "./login.css"; const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; -export default class Login extends React.Component { - constructor(props) { +interface LoginProps { + isAuthenticated: boolean; + userHasAuthenticated: (authenticated: boolean) => void; +} + +interface LoginState { + loading: boolean; + redirect: boolean; + email: string; + password: string; + emailValid: "success" | "error" | "warning" | undefined; + passwordValid: "success" | "error" | "warning" | undefined; +} + +export default class Login extends React.Component { + constructor(props: LoginProps) { super(props); this.state = { @@ -15,28 +29,30 @@ export default class Login extends React.Component { redirect: false, email: "", password: "", - emailValid: null, - passwordValid: null, + emailValid: undefined, + passwordValid: undefined, }; } - onEmailChange = (event) => { + onEmailChange = (event: React.FormEvent) => { + const target = event.target as HTMLInputElement; this.setState({ - email: event.target.value, - emailValid: emailRegex.test(event.target.value.toLowerCase()) ? 'success' : 'error' + email: target.value, + emailValid: emailRegex.test(target.value.toLowerCase()) ? 'success' : 'error' }); } - onPasswordChange = (event) => { + onPasswordChange = (event: React.FormEvent) => { + const target = event.target as HTMLInputElement; this.setState({ - password: event.target.value, - passwordValid: event.target.value.length < 8 ? 'error' : 'success' + password: target.value, + passwordValid: target.value.length < 8 ? 'error' : 'success' }); } - onLogin = async (event) => { + onLogin = async (event: React.FormEvent) => { event.preventDefault(); - this.setState({ isLoading: true }); + this.setState({ loading: true }); try { await Auth.signIn(this.state.email, this.state.password); @@ -44,7 +60,7 @@ export default class Login extends React.Component { this.setState({ redirect: true }) } catch (e) { alert(e.message); - this.setState({ isLoading: false }); + this.setState({ loading: false }); } } @@ -78,10 +94,8 @@ export default class Login extends React.Component { block bsSize="large" type="submit" - isLoading={this.state.isLoading} - text="Log in" disabled={this.state.passwordValid !== 'success' || this.state.emailValid !== 'success' }> - {this.state.isLoading && }Log in + {this.state.loading && }Log in
diff --git a/assets/src/modules/signup/Signup.js b/assets/src/modules/signup/Signup.tsx similarity index 66% rename from assets/src/modules/signup/Signup.js rename to assets/src/modules/signup/Signup.tsx index 6dc1ffc73..fad00da96 100644 --- a/assets/src/modules/signup/Signup.js +++ b/assets/src/modules/signup/Signup.tsx @@ -7,8 +7,27 @@ import "./home.css"; const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; -export default class Signup extends React.Component { - constructor(props) { +interface SignupProps { + isAuthenticated: boolean; + userHasAuthenticated: (authenticated: boolean) => void; +} + +interface SignupState { + loading: boolean; + email: string; + password: string; + confirmPassword: string; + confirmationCode: string; + emailValid: "success" | "error" | "warning" | undefined; + passwordValid: "success" | "error" | "warning" | undefined; + confirmPasswordValid: "success" | "error" | "warning" | undefined; + confirmationCodeValid: "success" | "error" | "warning" | undefined; + user: any; + redirect: boolean; +} + +export default class Signup extends React.Component { + constructor(props: SignupProps) { super(props); this.state = { @@ -17,43 +36,48 @@ export default class Signup extends React.Component { password: "", confirmPassword: "", confirmationCode: "", - emailValid: null, - passwordValid: null, - confirmPasswordValid: null, - confirmationCodeValid: null, - user: null + emailValid: undefined, + passwordValid: undefined, + confirmPasswordValid: undefined, + confirmationCodeValid: undefined, + user: undefined, + redirect: false }; } - onEmailChange = (event) => { + onEmailChange = (event: React.FormEvent) => { + const target = event.target as HTMLInputElement; this.setState({ - email: event.target.value, - emailValid: emailRegex.test(event.target.value.toLowerCase()) ? 'success' : 'error' + email: target.value, + emailValid: emailRegex.test(target.value.toLowerCase()) ? 'success' : 'error' }); } - onPasswordChange = (event) => { + onPasswordChange = (event: React.FormEvent) => { + const target = event.target as HTMLInputElement; this.setState({ - password: event.target.value, - passwordValid: event.target.value.length < 8 ? 'error' : 'success' + password: target.value, + passwordValid: target.value.length < 8 ? 'error' : 'success' }); } - onConfirmPasswordChange = (event) => { + onConfirmPasswordChange = (event: React.FormEvent) => { + const target = event.target as HTMLInputElement; this.setState({ - confirmPassword: event.target.value, - confirmPasswordValid: event.target.value !== this.state.password ? 'error' : 'success' + confirmPassword: target.value, + confirmPasswordValid: target.value !== this.state.password ? 'error' : 'success' }); } - onConfirmationCodeChange = (event) => { + onConfirmationCodeChange = (event: React.FormEvent) => { + const target = event.target as HTMLInputElement; this.setState({ - confirmationCode: event.target.value, - confirmationCodeValid: event.target.value.length > 0 ? 'error' : 'success' + confirmationCode: target.value, + confirmationCodeValid: target.value.length > 0 ? 'error' : 'success' }); } - onSignup = async (event) => { + onSignup = async (event: React.FormEvent) => { event.preventDefault(); this.setState({ loading: true }); @@ -69,7 +93,7 @@ export default class Signup extends React.Component { } } - onConfirm = async (event) => { + onConfirm = async (event: React.FormEvent) => { event.preventDefault(); this.setState({ loading: true }); @@ -104,10 +128,8 @@ export default class Signup extends React.Component { block bsSize="large" type="submit" - isLoading={this.state.loading} - text="Confirm" disabled={this.state.confirmationCodeValid === 'success'}> - {this.state.loading && }Log in + {this.state.loading && }Confirm ); @@ -151,8 +173,6 @@ export default class Signup extends React.Component { block bsSize="large" type="submit" - isLoading={this.state.loading} - text="Sign up" disabled={this.state.passwordValid !== 'success' || this.state.confirmPasswordValid !== 'success' || this.state.emailValid !== 'success'}> {this.state.loading && }Log in @@ -163,7 +183,7 @@ export default class Signup extends React.Component { render() { return (
- {this.state.user === null ? this.showSignupForm() : this.showConfirmationForm()} + {this.state.user === undefined ? this.showSignupForm() : this.showConfirmationForm()}
); } diff --git a/assets/src/react-app-env.d.ts b/assets/src/react-app-env.d.ts new file mode 100644 index 000000000..6431bc5fc --- /dev/null +++ b/assets/src/react-app-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/assets/src/registerServiceWorker.js b/assets/src/registerServiceWorker.ts similarity index 76% rename from assets/src/registerServiceWorker.js rename to assets/src/registerServiceWorker.ts index a3e6c0cfc..a79f4b449 100644 --- a/assets/src/registerServiceWorker.js +++ b/assets/src/registerServiceWorker.ts @@ -21,7 +21,7 @@ const isLocalhost = Boolean( 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); + 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 @@ -52,28 +52,30 @@ export default function register() { } } -function registerValidSW(swUrl) { +function registerValidSW(swUrl: string) { 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.'); + 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 => { @@ -81,14 +83,14 @@ function registerValidSW(swUrl) { }); } -function checkValidServiceWorker(swUrl) { +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 + response.headers.get('content-type')!.indexOf('javascript') === -1 ) { // No service worker found. Probably a different app. Reload the page. navigator.serviceWorker.ready.then(registration => { diff --git a/assets/src/types/aws-amplify-react.d.ts b/assets/src/types/aws-amplify-react.d.ts new file mode 100644 index 000000000..1181e15a3 --- /dev/null +++ b/assets/src/types/aws-amplify-react.d.ts @@ -0,0 +1 @@ +declare module 'aws-amplify-react'; \ No newline at end of file diff --git a/assets/tsconfig.json b/assets/tsconfig.json new file mode 100644 index 000000000..974f7716b --- /dev/null +++ b/assets/tsconfig.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "target": "es5", + "allowJs": false, + "skipLibCheck": false, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "preserve", + "lib": ["es2015", "es2017", "dom"], + "typeRoots": [ + "./src/types", + "./node_modules/@types" + ] + }, + "include": [ + "src" + ], + "exclude": [ + "./node_modules/*" + ] +}