Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial boilerplate migration to Typescript #62

Open
wants to merge 35 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
cedf7a1
Initial boilerplate migration to Typescript
gomezhyuuga Jul 7, 2018
cbef533
Adding CSS Normalize
gomezhyuuga Jul 7, 2018
948f236
Put CSS Reset in index.css
gomezhyuuga Jul 8, 2018
1494b63
Adjustments of TSLint variable names rules
gomezhyuuga Jul 8, 2018
7697488
Initial Routing implementation, see routes.ts
gomezhyuuga Jul 8, 2018
5b50ea1
TSLint Rule: ignore console logs warning
gomezhyuuga Jul 8, 2018
40f1d7c
ADD: TSConfig downlevelIteration: true
gomezhyuuga Jul 8, 2018
d715db1
Initial Redux Saga Boilerplate
gomezhyuuga Jul 8, 2018
b988f3b
.gitignore .env file
gomezhyuuga Jul 8, 2018
328279c
Initial Redux markup: Wrapping app into Provider
gomezhyuuga Jul 8, 2018
c1c7bc6
Iniital action: FETCH_TRENDING
gomezhyuuga Jul 8, 2018
3a7277f
Giphy API functions getTrending(), search()
gomezhyuuga Jul 8, 2018
645fd63
GIF interface definition
gomezhyuuga Jul 8, 2018
332df35
Initial GIFList Component
gomezhyuuga Jul 8, 2018
f1dd63d
Enable Redux Chrome Extension
gomezhyuuga Jul 8, 2018
19f4f7b
Extra CSS Base Styling
gomezhyuuga Jul 8, 2018
bfe89fa
HomeView using Redux/Saga see reduces/index.ts
gomezhyuuga Jul 8, 2018
ec566bf
Favorite function completed
gomezhyuuga Jul 8, 2018
7ea9c68
Favorite View completed
gomezhyuuga Jul 8, 2018
98dcd6f
LocalStorage implementation
gomezhyuuga Jul 8, 2018
0327be2
Search functionality
gomezhyuuga Jul 8, 2018
a8a36d1
Favs Search implemented
gomezhyuuga Jul 9, 2018
6ae00f7
General styling improvements
gomezhyuuga Jul 9, 2018
d478cde
Styling migration to lecture best practices
gomezhyuuga Jul 10, 2018
dc9b9e4
Initial tests for FavButton.tsx and App.tsx
gomezhyuuga Jul 11, 2018
101e772
FavButton tests
gomezhyuuga Jul 12, 2018
711a11b
GIFList tests
gomezhyuuga Jul 12, 2018
470aeef
API Tests
gomezhyuuga Jul 12, 2018
b7e684a
Search tests
gomezhyuuga Jul 12, 2018
645d330
Fixed static typing
gomezhyuuga Jul 12, 2018
c252675
Improved test for GIFList
gomezhyuuga Jul 12, 2018
28d0b91
Ignore src/index.tsx due to be boilerplate
gomezhyuuga Jul 12, 2018
45a775d
Improved Search test
gomezhyuuga Jul 12, 2018
14c3e86
FavsView.tsx tested
gomezhyuuga Jul 12, 2018
0f2fd6c
Redux Action Creators testing
gomezhyuuga Jul 12, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 0 additions & 14 deletions .babelrc

This file was deleted.

3 changes: 0 additions & 3 deletions .eslintignore

This file was deleted.

6 changes: 0 additions & 6 deletions .eslintrc

This file was deleted.

2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
.env.development.local
.env.test.local
.env.production.local
.env

npm-debug.log*
yarn-debug.log*
yarn-error.log*
.vscode/
5 changes: 5 additions & 0 deletions images.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
declare module '*.svg'
declare module '*.png'
declare module '*.jpg'

declare module '*.json'
56 changes: 45 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,26 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-scripts": "1.1.1"
"@types/react-redux": "^6.0.3",
"@types/redux-actions": "^2.3.0",
"axios": "^0.18.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",
"redux": "^4.0.0",
"redux-actions": "^2.4.0",
"redux-saga": "^0.16.0",
"styled-components": "^3.3.3"
},
"jest": {
"collectCoverageFrom": [
"**/src/**/*.{js,jsx}",
"!**/src/registerServiceWorker.{js,jsx}"
"**/src/**/*.{ts,tsx}",
"!**/src/registerServiceWorker.{ts,tsx}",
"!**/src/setupTests.{js,ts}",
"!**/src/index.tsx",
"!**/src/**/*.d.{ts,tsx}"
],
"coverageThreshold": {
"global": {
Expand All @@ -22,15 +34,37 @@
}
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"eject": "react-scripts eject",
"lint": "eslint ./",
"start": "react-scripts-ts start",
"build": "react-scripts-ts build",
"test": "yarn lint && yarn jest",
"jest": "react-scripts test --env=jsdom --coverage"
"eject": "react-scripts-ts eject",
"lint": "tslint -p tsconfig.json -c tslint.json",
"jest": "react-scripts-ts test --env=jsdom --watchAll --coverage"
},
"devDependencies": {
"@types/babel-core": "^6.25.5",
"@types/enzyme": "^3.1.11",
"@types/enzyme-adapter-react-16": "^1.0.2",
"@types/jest": "^23.1.5",
"@types/node": "^10.5.2",
"@types/react": "^16.4.6",
"@types/react-dom": "^16.0.6",
"@types/react-router-dom": "^4.2.7",
"@types/react-test-renderer": "^16.0.1",
"@types/redux-mock-store": "^1.0.0",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1"
"enzyme-adapter-react-16": "^1.1.1",
"enzyme-to-json": "^3.3.4",
"jest": "^23.4.0",
"jest-enzyme": "^6.0.2",
"jest-styled-components": "^5.0.1",
"react-test-renderer": "^16.4.1",
"redux-devtools-extension": "^2.13.5",
"redux-mock-store": "^1.5.3",
"ts-jest": "^22.4.6",
"typescript": "^2.9.2"
},
"resolutions": {
"jest": "^23.4.0"
}
}
28 changes: 0 additions & 28 deletions src/App.css

This file was deleted.

21 changes: 0 additions & 21 deletions src/App.js

This file was deleted.

1 change: 1 addition & 0 deletions src/App.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import './styles/App.global'
33 changes: 33 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as React from 'react';
import {BrowserRouter as Router} from 'react-router-dom';
import { Switch, Route, Redirect } from 'react-router-dom';
import { Provider} from 'react-redux';

import store from './store';
import ROUTES from './routes';
import Header from './components/presentational/Header';
import { Container } from './components/presentational/Layout';

import './App.style'

class App extends React.Component {
public render() {
return (
<Provider store={store}>
<Router>
<Container>
<Header />
<section>
<Switch>
{ROUTES.map(({path, component, exact}) =>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this specific case where we have few routes that are at the same level the benefit may not be that obvious, but remember that the mindset of React-router 4 is making routing dynamic instead of static. When defining your routes on a separate file you are still approaching this in a static way.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, should I move them to this single file?
Although, the dynamic routing could still be used in any other file connecting with router right?
I'm used to use single-file definitions for routes at the same level and use multiple files (dynamic) for nested routes or with a different context.

<Route key={path} path={path} exact={exact} component={component} />)}
<Redirect to='/home' />
</Switch>
</section>
</Container>
</Router>
</Provider>
);
}
}
export default App;
21 changes: 21 additions & 0 deletions src/actions/gifs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { createAction } from 'redux-actions'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


export const FETCH_TRENDING = 'FETCH_TRENDING';
export const FETCHED_TRENDING = 'FETCHED_TRENDING';

export const ADD_FAVORITE = 'ADD_FAVORITE';
export const REMOVE_FAVORITE = 'REMOVE_FAVORITE'
export const TOGGLE_FAVORITE = 'TOGGLE_FAVORITE';

export const SEARCH_TRENDING = 'SEARCH_TRENDING';

export const FILTER_FAVS = 'FILTER_FAVS';

export const fetch_gifs = createAction(FETCH_TRENDING);
export const fetched_gifs = createAction(FETCHED_TRENDING);

export const toggle_favorite = createAction(TOGGLE_FAVORITE, (payload: any) => payload);

export const search_trending = createAction(SEARCH_TRENDING, (payload: any) => payload);

export const filter_favs = createAction(FILTER_FAVS, (payload: any) => payload);
22 changes: 22 additions & 0 deletions src/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import axios from 'axios';

const API_URL = "https://api.giphy.com/v1/gifs";
const API_KEY = process.env.REACT_APP_GIPHY_KEY;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


const API = axios.create({ baseURL: API_URL, params: { api_key: API_KEY } });

export function getTrending() {
return API.get('/trending');
}

export function search(query: string) {
return API.get('/search', {
params: {
q: query,
limit: 25,
offset: 0,
rating: 'G',
lang: 'en'
}
});
}
29 changes: 29 additions & 0 deletions src/components/AppNav.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import styled from 'styled-components';
import { NavLink as RouterNavLink } from 'react-router-dom';

export const StyledNav = styled.nav`
border-bottom: 1px solid #FC4349;
margin-bottom: 1em;
color: #6DBCDB;
font-weight: bold;

ul {
display: flex;
justify-content: space-around;
text-align: center;
align-items: center;
height: 3.5em;
}

li { flex: 1; }

a {
text-decoration: none;
color: inherit;
padding: 1em;
}
`;

export const NavLink = styled(RouterNavLink)`
&.active { color: #FC4349; }
`
21 changes: 21 additions & 0 deletions src/components/AppNav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as React from 'react';
import ROUTES from '../routes';
import Search from './Search';

import { StyledNav, NavLink } from './AppNav.style'

const LINKS = ROUTES.map(({path, content}) =>
<li key={path}><NavLink to={path}>{content}</NavLink></li>);

class AppNav extends React.Component {
public render() {
return (<StyledNav>
<ul>
{LINKS}
<li><Search /></li>
</ul>
</StyledNav>);
}
}

export default AppNav;
26 changes: 26 additions & 0 deletions src/components/FavsSearch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch, bindActionCreators } from 'redux';

import { filter_favs as filter_favs_action } from '../actions/gifs';
import { SearchInput } from './Search.style';

class FavsSearch extends React.Component<any> {
public onSearch = (event: React.ChangeEvent<HTMLInputElement>) => {
const term = event.target.value;
return this.props.filter_favs(term);
}

public render() {
return <SearchInput type='text'
onChange={this.onSearch}
placeholder='Search in your favorites...' />;
}
}

function mapDispatchToProps(dispatch: Dispatch) {
return bindActionCreators({
filter_favs: filter_favs_action,
}, dispatch);
}
export default connect(null, mapDispatchToProps)(FavsSearch);
7 changes: 7 additions & 0 deletions src/components/FavsView.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import styled from 'styled-components';

export const _div_search = styled.div`
width: 100%;
max-width: 320px;
margin: 0 auto;
`;
36 changes: 36 additions & 0 deletions src/components/FavsView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as React from 'react';
import { IGIF } from '../types';
import GIFList from './presentational/GIFList';
import {connect} from 'react-redux';
import { Dispatch, bindActionCreators } from 'redux';
import FavsSearch from './FavsSearch';

import { _div_search } from './FavsView.style'

interface IFavsViewProps {
gifs: IGIF[]
}

export const FavsView = (props: IFavsViewProps) => {
return (<div>
<h1 className="center">Your favorite GIFS</h1>
<_div_search>
<FavsSearch />
</_div_search>
<GIFList gifs={props.gifs} />
</div>);
}

function filterFavs(favs: object, query: string) {
const gifs = Object.keys(favs).map(key => favs[key]);

// Don't filter if there is no query term
if (!query || query.length === 0) return gifs;

return gifs.filter((gif: IGIF) => gif.title.includes(query));
}

function mapStateToProps(state: any) {
return { gifs: filterFavs(state.favs, state.filter_favs) }
}
export default connect(mapStateToProps)(FavsView);
Loading