master c6620fe8e131 cached
52 files
65.4 KB
16.0k tokens
80 symbols
1 requests
Download .txt
Repository: goemen/react-material-ui-typescript
Branch: master
Commit: c6620fe8e131
Files: 52
Total size: 65.4 KB

Directory structure:
gitextract_wgb9fbz0/

├── .config/
│   └── tomahawkci.yml
├── .gitignore
├── Procfile
├── README.md
├── _config.yml
├── images.d.ts
├── package.json
├── public/
│   ├── index.html
│   └── manifest.json
├── server.js
├── src/
│   ├── App.css
│   ├── App.test.tsx
│   ├── App.tsx
│   ├── actions/
│   │   ├── App.Actions.ts
│   │   └── Helpers.ts
│   ├── alert/
│   │   └── Alert.tsx
│   ├── components/
│   │   ├── MailList.tsx
│   │   ├── TableHeader.tsx
│   │   └── TableToolbar.tsx
│   ├── data/
│   │   ├── mail.ts
│   │   ├── material.ts
│   │   └── users.ts
│   ├── index.css
│   ├── index.tsx
│   ├── navigation/
│   │   ├── App.Bar.tsx
│   │   ├── App.Drawer.tsx
│   │   └── styles.ts
│   ├── pages/
│   │   ├── Home.tsx
│   │   ├── account/
│   │   │   ├── Account.tsx
│   │   │   ├── Login.tsx
│   │   │   └── Profile.tsx
│   │   └── mail/
│   │       ├── Drafts.tsx
│   │       ├── Inbox.tsx
│   │       ├── Mail.tsx
│   │       └── Sent.tsx
│   ├── reducers/
│   │   ├── AuthenticationReducer.ts
│   │   ├── CombinedReducers.ts
│   │   └── UtilityReducer.ts
│   ├── registerServiceWorker.ts
│   ├── selectors/
│   │   └── index.ts
│   ├── spinner/
│   │   └── Spinner.tsx
│   ├── state/
│   │   ├── Alert.ts
│   │   ├── AppState.ts
│   │   ├── Helpers.ts
│   │   ├── Spinner.ts
│   │   ├── User.ts
│   │   └── Utility.ts
│   └── store/
│       └── Store.ts
├── tsconfig.json
├── tsconfig.prod.json
├── tsconfig.test.json
└── tslint.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .config/tomahawkci.yml
================================================
version: '1.0.0'

dependencies:
  - npm install --ignore-scripts

tasks:
  test:
    - npm run test

================================================
FILE: .gitignore
================================================
# dependencies
/node_modules

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
functions/
functions-src/

.vscode/settings.json


================================================
FILE: Procfile
================================================
web: npm run deploy

================================================
FILE: README.md
================================================
## Description
This is a boilerplate for React using Typescript, Material UI and Redux, React Router.

## Demo
*Visit [Demo link](https://material-ui-admin.herokuapp.com/)*
#### Login credentials
* username/email: *anything*
* password: *anything*

## Features
### Authentication
The app uses redux to manage the authentication state, and uses redux-auth-wrapper library to guard the routes
#### Pages
*  Login Page

### Admin dashboard
The template comes with responsive modern charts, analytics, tables that are easily customizable to meet your data. 

### Other pages
* Inbox, Outbox, Drafts
* Profile Page (coming soon)

## How to run
### Local development
* Clone the project and cd into project
* npm install
* npm start and go to [link](*http://localhost:3000*)

### Deployment
* npm install
* npm run build
* npm run deploy

## Key technologies & Libraries used
* Material UI (1.1.0) - (for ui components)
* React Router
* Redux
* Typescript
* React (of course)





================================================
FILE: _config.yml
================================================
theme: jekyll-theme-cayman

================================================
FILE: images.d.ts
================================================
declare module '*.svg'
declare module '*.png'
declare module '*.jpg'


================================================
FILE: package.json
================================================
{
  "name": "react-boilerplate",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@material-ui/core": "^1.5.1",
    "@material-ui/icons": "^1.1.1",
    "@types/immutable": "^3.8.7",
    "@types/lodash": "^4.14.119",
    "@types/moment": "^2.13.0",
    "@types/react-redux": "^6.0.13",
    "@types/react-router-dom": "^4.3.1",
    "@types/recharts": "^1.1.6",
    "@types/redux": "^3.6.31",
    "@types/redux-auth-wrapper": "^2.0.9",
    "@types/redux-devtools-extension": "^2.13.2",
    "@types/redux-thunk": "^2.1.32",
    "@types/reselect": "^2.2.0",
    "classnames": "^2.2.6",
    "express": "^4.16.4",
    "immutable": "^3.8.2",
    "lodash": "^4.17.11",
    "mobx": "^4.8.0",
    "mobx-react-devtools": "^5.0.1",
    "moment": "^2.23.0",
    "querystring": "^0.2.0",
    "randomcolor": "^0.5.3",
    "react": "^16.7.0",
    "react-dom": "^16.7.0",
    "react-mobx": "0.0.3",
    "react-redux": "^5.1.1",
    "react-router-dom": "^4.3.1",
    "react-scripts-ts": "2.16.0",
    "recharts": "^1.4.2",
    "redux": "^4.0.1",
    "redux-auth-wrapper": "^2.0.3",
    "redux-devtools-extension": "^2.13.7",
    "redux-rest-resource": "^0.18.0",
    "redux-thunk": "^2.3.0",
    "reselect": "^3.0.1"
  },
  "scripts": {
    "start": "react-scripts-ts start",
    "build": "react-scripts-ts build",
    "test": "react-scripts-ts test --env=jsdom",
    "postinstall": "npm run build",
    "deploy": "node server.js",
    "eject": "react-scripts-ts eject"
  },
  "devDependencies": {
    "@types/jest": "^22.2.3",
    "@types/node": "^10.12.18",
    "@types/react": "^16.7.18",
    "@types/react-dom": "^16.0.11",
    "babel-plugin-transform-decorators-legacy": "^1.3.4",
    "typescript": "^3.2.2"
  },
  "babel": {
    "plugins": [
      "transform-decorators-legacy"
    ],
    "presets": [
      "react-app"
    ]
  }
}


================================================
FILE: public/index.html
================================================
<!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">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500">
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">

    <!--
      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>Tomahawk</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>


================================================
FILE: public/manifest.json
================================================
{
  "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"
}


================================================
FILE: server.js
================================================
const express = require('express');
const path = require('path');
const app = express();

app.use(express.static(path.join(__dirname, 'build')));
app.get('*', function (req, res) {
  res.sendFile(path.join(__dirname, 'build', 'index.html'));
});

app.listen(process.env.PORT || 3000);


================================================
FILE: src/App.css
================================================
.App {
  text-align: center;
}

.App-logo {
  animation: App-logo-spin infinite 20s linear;
  height: 80px;
}

.App-header {
  background-color: #222;
  height: 150px;
  padding: 20px;
  color: white;
}

.App-title {
  font-size: 1.5em;
}

.App-intro {
  font-size: large;
}

@keyframes App-logo-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}


================================================
FILE: src/App.test.tsx
================================================
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';

it('renders without crashing', () => {
  const div = document.createElement('div');
  ReactDOM.render(<App />, div);
  ReactDOM.unmountComponentAtNode(div);
});


================================================
FILE: src/App.tsx
================================================
import * as React from 'react';
import './App.css';
import AppNavBar from './navigation/App.Bar';
import { BrowserRouter as Router } from 'react-router-dom';
import { Provider } from 'react-redux';
import { store } from './store/Store';
import blue from '@material-ui/core/colors/blue';
import { createMuiTheme, MuiThemeProvider } from '@material-ui/core';
import { pink } from '@material-ui/core/colors';

const theme = createMuiTheme({
  palette: {
    primary: blue,
    secondary: pink
  }
})
class App extends React.Component {
  public render() {
    return (
      <Provider store={store}>
        <Router>
          <MuiThemeProvider theme={theme}>
            <AppNavBar />
          </MuiThemeProvider>
        </Router>
      </Provider>
    );
  }
}

export default App;


================================================
FILE: src/actions/App.Actions.ts
================================================
import { IAppAction, ActionType } from './Helpers';
import { match } from 'react-router';
import { Utility } from '../state/Utility';
import { Alert } from '../state/Alert';
import { Spinner } from '../state/Spinner';
import { User } from '../state/User';

export interface IApplicationProps {
    openDrawer: () => IAppAction;
    closeDrawer: () => IAppAction;
    showPopup: (alert: Alert) => IAppAction;
    closePopup: () => IAppAction;  
    showSpinner: (message: string) => IAppAction;
    hideSpinner: () => IAppAction; 
    login: (data: any) => IAppAction; 
    logout: () => IAppAction;
    createUser: (content: any) => any;
    getUser: (id: any) => any;
    fetchUsers: (context?: any) => any;
    updateUser: (context: any) => any;
    deleteUser: (context: any) => any;
    createMaterial: (content: any) => any;
    getMaterial: (id: any) => any;
    fetchMaterials: (context?: any) => any;
    updateMaterial: (context: any) => any;
    deleteMaterial: (context: any) => any;
    getMail: (id: any) => any;
    fetchMails: (context?: any) => any;
    updateMail: (context: any) => any;
    deleteMail: (context: any) => any;
    match: match<any>,
    location: any,
    history: any,
    utility: Utility;
    authentication: User;
    users: any;
    materials: any;
    mail: any[];
    materialCharts: Array<{name: string, value: number, fill: string}>;
}

export const openDrawer = (): IAppAction => {
    return {
        type: ActionType.OPEN_DRAWER
    };
};

export const closeDrawer = (): IAppAction => {
    return {
        type: ActionType.CLOSE_DRAWER
    };
};

export const showPopup = (data: Alert): IAppAction => {
    return {
        type: ActionType.OPEN_ALERT,
        payload: data
    };
};

export const closePopup = (): IAppAction => {
    return {
        type: ActionType.CLOSE_ALERT
    };
};

export const showSpinner = (message: string): IAppAction => {
    return {
        type: ActionType.OPEN_SPINNER,
        payload: new Spinner({message})
    };
};

export const hideSpinner = (): IAppAction => {
    return {
        type: ActionType.CLOSE_SPINNER
    };
};

export const login = (data: any): IAppAction => {
    return { type: ActionType.LOGIN_REQUEST, payload: data };
};

export const logout = (): IAppAction => {
    return { type: ActionType.LOGOUT_REQUEST };
};


================================================
FILE: src/actions/Helpers.ts
================================================
import { Action } from "redux";

export enum ActionType {
    OPEN_DRAWER,
    CLOSE_DRAWER,
    OPEN_ALERT,
    CLOSE_ALERT,
    OPEN_SPINNER,
    CLOSE_SPINNER,
    LOGIN_REQUEST,
    LOGIN_SUCCESS,
    LOGIN_FAIL,
    LOGOUT_REQUEST,
    LOGOUT_SUCCESS,
    LOGOUT_FAIL
}

export interface IAppAction extends Action<ActionType> {
    payload?: any;
}

================================================
FILE: src/alert/Alert.tsx
================================================
import * as React from 'react';
import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import DialogTitle from '@material-ui/core/DialogTitle';
import { Alert } from '../state/Alert';

interface IAlertProps {
    data?: Alert;
    handleClose: () => void;
    children?: any;
}
export class AlertDialog extends React.Component<IAlertProps, {}> {

    public handleClose = () => {
        this.props.handleClose();
    };

    public render() {
        return (

            <Dialog
                open={this.props.data !== null}
                onClose={this.handleClose}
                aria-labelledby="alert-dialog-title"
                aria-describedby="alert-dialog-description"
            >
                <DialogTitle id="alert-dialog-title">{this.props.data.title}</DialogTitle>
                <DialogContent>
                    <DialogContentText id="alert-dialog-description">
                    { this.props.data.message }
            </DialogContentText>
                </DialogContent>
                <DialogActions>
                    <Button onClick={this.handleClose} color="primary">
                        Disagree
            </Button>
                    <Button onClick={this.handleClose} color="primary" autoFocus={true}>
                        Agree
            </Button>
                </DialogActions>
            </Dialog>
        );
    }
}


================================================
FILE: src/components/MailList.tsx
================================================
import * as React from 'react';
import { withStyles, Theme } from '@material-ui/core/styles';
import ExpansionPanel from '@material-ui/core/ExpansionPanel';
import ExpansionPanelDetails from '@material-ui/core/ExpansionPanelDetails';
import ExpansionPanelSummary from '@material-ui/core/ExpansionPanelSummary';
import ExpansionPanelActions from '@material-ui/core/ExpansionPanelActions';
import Typography from '@material-ui/core/Typography';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import { Avatar } from '@material-ui/core';
import Divider from '@material-ui/core/Divider';
import Button from '@material-ui/core/Button';

const styles = (theme: Theme) => ({
    root: {
        width: '100%',
    },
    avatar: {
        marginRight: 5
    },
    summary: {
        display: 'flex',
        alignContent: 'center',
        alignItems: 'center',
    },
    heading: {
        fontSize: theme.typography.pxToRem(15),
        height: '100%',
        verticalAlign: 'middle',
        flexBasis: '33.33%',
        flexShrink: 0,
        color: theme.palette.text.secondary,
    },
    secondaryHeading: {
        fontSize: theme.typography.pxToRem(15),
    },
});

interface IMailListProps {
    items: any[];
    classes: any;
}

interface IState {
    expanded?: number;
}

class MailList extends React.Component<IMailListProps, IState> {
    public state: IState = {
        expanded: null,
    };

    private handleChange = (panel: any) => (event: any, expanded: any) => {
        this.setState({
            expanded: expanded ? panel : false,
        });
    };

    public render() {
        const { classes } = this.props;
        const { expanded } = this.state;

        return (
            <div className={classes.root}>
                {this.props.items.map((item: any) => {
                    return (

                        <ExpansionPanel key={item.id} expanded={expanded === item.id} onChange={this.handleChange(item.id)}>
                            <ExpansionPanelSummary className={classes.summary} expandIcon={<ExpandMoreIcon />}>
                                <Avatar className={classes.avatar} src={item.avatar} />
                                <Typography className={classes.heading}>{item.from}</Typography>
                                <Typography className={classes.secondaryHeading}>{item.subject}</Typography>
                            </ExpansionPanelSummary>
                            <ExpansionPanelDetails>
                                <Typography>
                                    {item.content}
                                </Typography>
                            </ExpansionPanelDetails>
                            <Divider />
                            <ExpansionPanelActions>
                                <Button size="small">Cancel</Button>
                                <Button size="small" color="primary">
                                    Delete
                                </Button>
                            </ExpansionPanelActions>
                        </ExpansionPanel>
                    );
                })}
            </div>
        );
    }
}

export default withStyles(styles)(MailList);


================================================
FILE: src/components/TableHeader.tsx
================================================
import * as React from 'react';
import { TableHead, TableRow, TableCell, Checkbox, Tooltip, TableSortLabel } from '@material-ui/core';

export interface IColumnData {
    id?: string;
    numeric?: boolean;
    disablePadding?: boolean;
    label?: string;
}

interface IEnhancedTableHeadProps {
    onRequestSort?: (event: any, property: any) => any;
    onSelectAllClick?: any;
    order?: any;
    orderBy?: any;
    selected?: number;
    count?: number;
    columns?: IColumnData[];
}

export class EnhancedTableHead extends React.Component<IEnhancedTableHeadProps, {}> {
    private createSortHandler = (property: any) => (event: any) => {
        this.props.onRequestSort(event, property);
    };

    public render() {
        const { columns, onSelectAllClick, order, orderBy, selected, count } = this.props;

        return (
            <TableHead>
                <TableRow>
                    <TableCell padding="checkbox">
                        <Checkbox
                            indeterminate={selected > 0 && selected < count}
                            checked={selected === count}
                            onChange={onSelectAllClick}
                        />
                    </TableCell>
                    {columns.map(column => {
                        return (
                            <TableCell
                                key={column.id}
                                numeric={column.numeric}
                                padding={column.disablePadding ? 'none' : 'default'}
                                sortDirection={orderBy === column.id ? order : false}
                            >
                                <Tooltip
                                    title="Sort"
                                    placement={column.numeric ? 'bottom-end' : 'bottom-start'}
                                    enterDelay={300}
                                >
                                    <TableSortLabel
                                        active={orderBy === column.id}
                                        direction={order}
                                        onClick={this.createSortHandler(column.id)}
                                    >
                                        {column.label}
                                    </TableSortLabel>
                                </Tooltip>
                            </TableCell>
                        );
                    }, this)}
                </TableRow>
            </TableHead>
        );
    }
}

================================================
FILE: src/components/TableToolbar.tsx
================================================
import * as React from 'react';
import { Toolbar, Typography, Tooltip, IconButton, Theme, withStyles } from '@material-ui/core';
const classNames = require('classnames');
import DeleteIcon from '@material-ui/icons/Delete';
import FilterListIcon from '@material-ui/icons/FilterList';

interface IEnhancedTableToolbarProps {
    classes?: any;
    selected?: number;
}

class EnhancedTableToolbar extends React.Component<IEnhancedTableToolbarProps, {}> {

    public render(): JSX.Element {
        const { selected, classes } = this.props;

        return (
            <Toolbar
                className={classNames(classes.root, {
                    [classes.highlight]: selected > 0,
                })}
            >
                <div className={classes.title}>
                    {selected > 0 ? (
                        <Typography color="inherit" variant="subheading">
                            {selected} selected
            </Typography>
                    ) : (
                            <Typography variant="title" id="tableTitle">
                                Nutrition
            </Typography>
                        )}
                </div>
                <div className={classes.spacer} />
                <div className={classes.actions}>
                    {selected > 0 ? (
                        <Tooltip title="Delete">
                            <IconButton aria-label="Delete">
                                <DeleteIcon />
                            </IconButton>
                        </Tooltip>
                    ) : (
                            <Tooltip title="Filter list">
                                <IconButton aria-label="Filter list">
                                    <FilterListIcon />
                                </IconButton>
                            </Tooltip>
                        )}
                </div>
            </Toolbar>
        );
    }
}

const toolbarStyles = (theme: Theme) => ({
    root: {
        paddingRight: theme.spacing.unit,
    },
    highlight:
        theme.palette.type === 'light'
            ? {
                color: theme.palette.secondary.main,
                backgroundColor: `lighten(${theme.palette.secondary.light}, 0.85)`,
            }
            : {
                color: theme.palette.text.primary,
                backgroundColor: theme.palette.secondary.dark,
            },
    spacer: {
        flex: '1 1 100%',
    },
    actions: {
        color: theme.palette.text.secondary,
    },
    title: {
        flex: '0 0 auto',
    },
});

export default withStyles(toolbarStyles)(EnhancedTableToolbar as any);


================================================
FILE: src/data/mail.ts
================================================
const Resourcer = require('redux-rest-resource');

export const { types, actions, rootReducer } = Resourcer.createResource({
    name: 'mail',
    url: `https://5b1b0a966e0fd400146aaee2.mockapi.io/mail/:id`
});


================================================
FILE: src/data/material.ts
================================================
const Resourcer = require('redux-rest-resource');

export const { types, actions, rootReducer } = Resourcer.createResource({
    name: 'material',
    url: `https://5b1b0a966e0fd400146aaee2.mockapi.io/materials/:id`
});


================================================
FILE: src/data/users.ts
================================================
const Resourcer = require('redux-rest-resource');

export const { types, actions, rootReducer } = Resourcer.createResource({
    name: 'user',
    url: `https://5b1b0a966e0fd400146aaee2.mockapi.io/users/:id`
});


================================================
FILE: src/index.css
================================================
body {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
}


================================================
FILE: src/index.tsx
================================================
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';
import './index.css';
import registerServiceWorker from './registerServiceWorker';

ReactDOM.render(
  <App />,
  document.getElementById('root') as HTMLElement);
registerServiceWorker();


================================================
FILE: src/navigation/App.Bar.tsx
================================================
//#region 
import * as React from 'react';
const classNames = require('classnames');
import { withStyles } from '@material-ui/core/styles';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import IconButton from '@material-ui/core/IconButton';
import MenuIcon from '@material-ui/icons/Menu';
import { ListItemText, Menu, MenuItem, Badge, Avatar } from '@material-ui/core';
import { Route, withRouter } from 'react-router-dom';
import Hidden from '@material-ui/core/Hidden';
import { styles } from './styles';
import { IApplicationProps } from '../actions/App.Actions';
import * as AppActionCreators from '../actions/App.Actions';
import { AppState, isAuthenticated } from '../state/AppState';
import { connect } from 'react-redux';
import * as _ from 'lodash';
import { bindActionCreators, Dispatch} from 'redux';
import { Alert } from '../state/Alert';
import { AlertDialog } from '../alert/Alert';
import SpinnerDialog from '../spinner/Spinner';
import { AccountPage } from '../pages/account/Account';
import { MailPage } from '../pages/mail/Mail';
import HomePage from '../pages/Home';
import AccountCircle from '@material-ui/icons/AccountCircle';
import { actions as UserActionCreators } from '../data/users';
import { actions as MailActionCreators } from '../data/mail';
import { actions as MaterialActionCreators } from '../data/material';
import { getMaterialChartItems, getMailitems } from '../selectors';
import AppDrawer from './App.Drawer';
import NotificationIcon from '@material-ui/icons/Notifications';
//#endregion

interface IAppProps extends IApplicationProps {
  classes: any;
  theme?: any;
}

interface IState {
  anchorEl: any;
  notificationEl: any;
}

class MiniDrawer extends React.Component<IAppProps, IState> {

  public state: IState = {
    anchorEl: null,
    notificationEl: null
  };

  public componentWillMount() {
    this.props.fetchUsers();
    this.props.fetchMaterials();
    this.props.fetchMails();
  }

  private handleNotificationMenu = (event: any) => {
    this.setState({ notificationEl: event.currentTarget });
  };

  private handleNotificationMenuClose = () => {
    this.setState({ notificationEl: null });
  };

  private handleMenu = (event: any) => {
    this.setState({ anchorEl: event.currentTarget });
  };

  private handleMenuClose = (path?: string) => {
    this.setState({ anchorEl: null });
    this.navigate(path);
  };

  public handleLogout = () => {
    this.props.logout();
    this.handleMenuClose();
  };

  private navigate = (path?: string) => {
    if (path) {
      this.props.history.push(path);
    }
  }

  public handleDrawerOpen = () => {
    this.props.openDrawer();
  };

  public handleDrawerClose = () => {
    this.props.closeDrawer();
  };

  public showPopup = () => {
    this.props.showPopup(new Alert({
      title: "Testing title",
      message: "This is a very long message, expect alert to be very wide"
    }))
  }

  public showSpinner = () => {
    this.props.showSpinner("I am loading here please...")
  }

  private renderAlert(): JSX.Element {
    if (this.props.utility.alert) {
      return (
        <AlertDialog
          handleClose={this.props.closePopup}
          data={this.props.utility.alert}
        />
      );
    }

    return null
  }

  private renderSpinner(): JSX.Element {
    if (this.props.utility.spinner) {
      return (
        <SpinnerDialog
          message={this.props.utility.spinner.message}
        />
      );
    }

    return null
  }

  private renderNotifications(notifications: any[]) {
    const { classes } = this.props;
    return (
      <Menu
        id="notifications"
        anchorEl={this.state.notificationEl}
        anchorOrigin={{
          vertical: 'top',
          horizontal: 'right',
        }}
        transformOrigin={{
          vertical: 'top',
          horizontal: 'right',
        }}
        className={classes.notifications}
        open={Boolean(this.state.notificationEl)}
        onClose={this.handleNotificationMenuClose}  
      >
          {notifications.map((n: any) => (
            <MenuItem key={n.id} onClick={this.handleNotificationMenuClose} dense={true} button={true} className={classes.notificationListItem}>
              <Avatar src={n.avatar} />
              <ListItemText primary={n.subject} />
            </MenuItem>
          ))}
      </Menu>
    );
  }

  private renderAppBar() {
    if (this.props.authentication) {
      const { classes, utility } = this.props;
      const { anchorEl, notificationEl } = this.state;
      const open = Boolean(anchorEl);
      const notificationsOpen = Boolean(notificationEl);
      const unreadMessages = this.props.mail.filter(x => x.seen === false);

      return (
        <AppBar
          position="fixed"
          className={classNames(classes.appBar, utility.drawerOpen && classes.appBarShift)}
        >
          <Toolbar disableGutters={!utility.drawerOpen}>
            <IconButton
              color="inherit"
              aria-label="open drawer"
              onClick={this.handleDrawerOpen}
              className={classNames(classes.menuButton, utility.drawerOpen && classes.hide)}
            >
              <MenuIcon />
            </IconButton>
            <Typography className={classes.fillSpace} variant="title" color="inherit" noWrap={true}>
              Tomahawk
            </Typography>
            <div>
              <IconButton
                aria-owns={notificationsOpen ? 'notifications' : null}
                aria-haspopup="true"
                color="inherit"
                onClick={this.handleNotificationMenu}
              >
                <Badge badgeContent={unreadMessages.length} color="secondary">
                  <NotificationIcon />
                </Badge>
              </IconButton>
              {this.renderNotifications(unreadMessages)}
              <IconButton
                aria-owns={open ? 'menu-appbar' : null}
                aria-haspopup="true"
                onClick={this.handleMenu}
                color="inherit"
              >
                <AccountCircle />
              </IconButton>
              <Menu
                id="menu-appbar"
                anchorEl={anchorEl}
                anchorOrigin={{
                  vertical: 'top',
                  horizontal: 'right',
                }}
                transformOrigin={{
                  vertical: 'top',
                  horizontal: 'right',
                }}
                open={open}
                onClose={this.handleMenuClose.bind(this, null)}
              >
                <MenuItem onClick={this.handleMenuClose.bind(this, '/account')}>{this.props.authentication.name}</MenuItem>
                <MenuItem onClick={this.handleLogout}>Logout</MenuItem>
              </Menu>
            </div>
          </Toolbar>
        </AppBar>
      );
    }

    return null;
  }

  private renderAccount = () => {
    return (
      <AccountPage user={this.props.authentication} login={this.props.login} match={this.props.match} location={this.props.location} />
    );
  }

  private renderDrawer() {
    const { utility, authentication } = this.props;
    return (
      <Hidden mdDown={!utility.drawerOpen && true}>
        <AppDrawer
          utility={utility}
          authentication={authentication}
          handleDrawerClose={this.handleDrawerClose}
        />
      </Hidden>
    );
  }

  public render() {
    const { classes } = this.props;
    const Dashboard = isAuthenticated((props: any): any => {
      return (
        <HomePage
          users={this.props.users}
          fetchUsers={this.props.fetchUsers}
          materialChartData={this.props.materialCharts}
        />
      );
    });

    const MailBoard = isAuthenticated((props: any): any => {
      return (
        <MailPage
          mail={this.props.mail}
        />
      );
    });


    return (
      <div className={classes.root}>
        {this.renderAppBar()}
        {this.renderDrawer()}

        <main className={classes.content}>
          <div className={classes.toolbar} />
          <Route path='/' exact={true} component={Dashboard} />
          <Route path='/dashboard' component={Dashboard} />
          <Route path='/mail' component={MailBoard} />
          <Route path='/account' render={this.renderAccount} />
          {this.renderAlert()}
          {this.renderSpinner()}
        </main>
      </div>
    );
  }
}

const mapStateToProps = (state: AppState) => ({
  utility: state.utility,
  authentication: state.authentication,
  users: state.users,
  materials: state.materials,
  materialCharts: getMaterialChartItems(state),
  mail: getMailitems(state)
});

const mapDispatchtoProps = (dispatch: Dispatch) =>
  bindActionCreators(_.assign({}, AppActionCreators, MailActionCreators,
    UserActionCreators, MaterialActionCreators), dispatch);

export default withRouter(connect(mapStateToProps, mapDispatchtoProps)(withStyles(styles as any, { withTheme: true })(MiniDrawer as any)) as any);


================================================
FILE: src/navigation/App.Drawer.tsx
================================================
import * as React from 'react';
import InboxIcon from '@material-ui/icons/Inbox';
import DraftsIcon from '@material-ui/icons/Drafts';
import SendIcon from '@material-ui/icons/Send';
import AccountCircleIcon from '@material-ui/icons/AccountCircle';
import DashboardIcon from '@material-ui/icons/Dashboard';
import { Drawer, IconButton, Divider, Theme, ListItem, ListItemIcon, ListItemText, withStyles } from '@material-ui/core';
import ChevronLeftIcon from '@material-ui/icons/ChevronLeft';
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
import { User } from '../state/User';
import { Utility } from '../state/Utility';
import { NavLink } from 'react-router-dom';
import { styles } from './styles';
const classNames = require('classnames');

interface IAppDrawer {
    authentication?: User;
    utility: Utility;
    classes?: any;
    theme?: Theme;
    handleDrawerClose?: () => void;
}

class AppDrawer extends React.Component<IAppDrawer, {}> {
    public routes = [
        { path: '/', title: 'Dashboard', icon: () => <DashboardIcon /> },
        { path: '/mail/inbox', title: 'Inbox', icon: () => <InboxIcon /> },
        { path: '/mail/sent', title: 'Sent', icon: () => <SendIcon /> },
        { path: '/mail/drafts', title: 'Drafts', icon: () => <DraftsIcon /> },
        { path: '/account', title: 'Profile', icon: () => <AccountCircleIcon /> }
    ]

    public render(): JSX.Element {
        const { authentication, classes, utility, theme } = this.props;
        return (
            <Drawer
                hidden={!authentication}
                variant="permanent"
                classes={{
                    paper: classNames(classes.drawerPaper, !utility.drawerOpen && classes.drawerPaperClose),
                }}
                open={utility.drawerOpen}
            >
                <div className={classes.toolbar}>
                    <IconButton onClick={this.props.handleDrawerClose}>
                        {theme.direction === 'rtl' ? <ChevronRightIcon /> : <ChevronLeftIcon />}
                    </IconButton>
                </div>
                <Divider />
                {this.routes.map((route, index) => {
                    return (
                        <NavLink key={index} exact={true} activeClassName={classes.current} className={classes.link} to={route.path} >
                            <ListItem button={true}>
                                <ListItemIcon>
                                    {route.icon()}
                                </ListItemIcon>
                                <ListItemText primary={route.title} />
                            </ListItem>
                        </NavLink>
                    );
                })}
                <Divider />
            </Drawer>
        );
    }
}

export default withStyles(styles as any, { withTheme: true })(AppDrawer as any) as any;

================================================
FILE: src/navigation/styles.ts
================================================
import { Theme } from "@material-ui/core";

const drawerWidth = 240;

export const styles = (theme: Theme) => ({
    root: {
      flexGrow: 1,
      height: '100vh',
      minHeight: '100%',
      zIndex: 1,
      overflow: 'hidden',
      position: 'relative',
      display: 'flex',
      width: '100%',
      backgroundColor: theme.palette.background.default,
    },
    appBar: {
      zIndex: theme.zIndex.drawer + 1,
      transition: theme.transitions.create(['width', 'margin'], {
        easing: theme.transitions.easing.sharp,
        duration: theme.transitions.duration.leavingScreen,
      }),
      [theme.breakpoints.up('md')]: {
        width: `100%`,
      },
    },
    appBarShift: {
      marginLeft: drawerWidth,
      width: `calc(100% - ${drawerWidth}px)`,
      transition: theme.transitions.create(['width', 'margin'], {
        easing: theme.transitions.easing.sharp,
        duration: theme.transitions.duration.enteringScreen,
      }),
    },
    menuButton: {
      marginLeft: 12,
      marginRight: 36,
    },
    hide: {
      display: 'none',
    },
    drawerPaper: {
      position: 'relative',
      top: 0,
      whiteSpace: 'nowrap',
      width: drawerWidth,
      transition: theme.transitions.create('width', {
        easing: theme.transitions.easing.sharp,
        duration: theme.transitions.duration.enteringScreen,
      })
  
    },
    drawerPaperClose: {
      overflowX: 'hidden',
      transition: theme.transitions.create('width', {
        easing: theme.transitions.easing.sharp,
        duration: theme.transitions.duration.leavingScreen,
      }),
      width: theme.spacing.unit * 7,
      [theme.breakpoints.up('sm')]: {
        width: theme.spacing.unit * 9,
      },
    },
    toolbar: {
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'flex-end',
      padding: '0 8px',
      ...theme.mixins.toolbar,
    },
    content: {
      flexGrow: 1,
      backgroundColor: theme.palette.background.default,
      padding: theme.spacing.unit * 3,
      minHeight: '100%',
      height: '100%',
      flex: '1 1 auto',
      overflowY: 'scroll'
    },
    button: {
      margin: theme.spacing.unit,
    },
    link: {
      textDecoration: 'none',
    },
    current: {
      color: 'red !important',
    },
    notifications: {
      overflowX: 'hidden'
    },
    fillSpace: {
      flex: '1 1 auto'
    }
  });

================================================
FILE: src/pages/Home.tsx
================================================
import * as React from 'react';
import {
    Theme, withStyles, Paper, Table, TableHead, TableRow,
    TableCell, TableBody, TablePagination, Grid, Typography
} from '@material-ui/core';
import { BarChart, CartesianGrid, XAxis, YAxis, Bar, Tooltip, Legend, PieChart, Pie, ResponsiveContainer } from 'recharts';
const classNames = require('classnames');
import GroupIcon from '@material-ui/icons/Group';
import MailIcon from '@material-ui/icons/Mail';
import SettingsIcon from '@material-ui/icons/Settings';
import BusinessIcon from '@material-ui/icons/BusinessCenter';

interface IDashboardProps {
    fetchUsers: (context?: any) => void;
    users: any;
    materialChartData: any[];
    classes?: any;
    theme?: any;
    children?: any;
}

interface IPageState {
    usersTablePage?: number;
    usersTableRowsPerPage: number;
}

class HomePage extends React.Component<IDashboardProps, IPageState> {

    public state: IPageState = {
        usersTablePage: 0,
        usersTableRowsPerPage: 5
    };

    private handleChangeUsersPage = (event: any, page: number) => {
        console.log(event);
        this.setState({ usersTablePage: page });
    };

    private handleChangeTableRowsPerPage = (event: any) => {
        this.setState({ usersTableRowsPerPage: event.target.value });
    };

    private renderUsers(): JSX.Element {
        const { users, classes } = this.props;
        if (!users) {
            return null;
        }

        return (
            <Paper className={classNames(classes.paper, classes.users)}>
                <h3 className={classes.sectionTitle}>Customers</h3>
                <Table className={classes.table}>
                    <TableHead>
                        <TableRow>
                            <TableCell>Id</TableCell>
                            <TableCell>Name</TableCell>
                            <TableCell>Email</TableCell>
                        </TableRow>
                    </TableHead>
                    <TableBody>
                        {users.items.slice(this.state.usersTablePage * this.state.usersTableRowsPerPage,
                            this.state.usersTablePage * this.state.usersTableRowsPerPage + this.state.usersTableRowsPerPage).map((n: any) => {
                                return (
                                    <TableRow key={n.id}>
                                        <TableCell component="th" scope="row">
                                            {n.id}
                                        </TableCell>
                                        <TableCell>{n.name}</TableCell>
                                        <TableCell>{n.email}</TableCell>
                                    </TableRow>
                                );
                            })}
                    </TableBody>
                </Table>
                <TablePagination
                    component="div"
                    count={users.items.length}
                    rowsPerPage={this.state.usersTableRowsPerPage}
                    page={this.state.usersTablePage}
                    backIconButtonProps={{
                        'aria-label': 'Previous Page',
                    }}
                    nextIconButtonProps={{
                        'aria-label': 'Next Page',
                    }}
                    onChangePage={this.handleChangeUsersPage}
                    onChangeRowsPerPage={this.handleChangeTableRowsPerPage}
                />
            </Paper>
        );

    }

    private renderRadialBarChart(): JSX.Element {
        return (
            <Paper className={this.props.classes.paper}>
                <h3 className={this.props.classes.sectionTitle}>Material Inventory</h3>
                <ResponsiveContainer width="100%" height={300}>
                    <PieChart>
                        <Pie
                            data={this.props.materialChartData}
                            dataKey="value"
                            nameKey="name"
                            cx="50%"
                            cy="50%"
                            label={true}
                            fill="#8884d8" />
                        <Legend />
                    </PieChart>
                </ResponsiveContainer>
            </Paper>
        );
    }

    private renderBarChart(): JSX.Element {
        return (
            <Paper className={this.props.classes.paper}>
                <h3 className={this.props.classes.sectionTitle}>Material Sales</h3>
                <ResponsiveContainer width="100%" height={300}>
                    <BarChart data={this.props.materialChartData}>
                        <CartesianGrid strokeDasharray="3 3" />
                        <XAxis dataKey="name" />
                        <YAxis />
                        <Tooltip />
                        <Bar dataKey="value" fill="#8884d8" />
                    </BarChart>
                </ResponsiveContainer>
            </Paper>
        );
    }

    public render(): JSX.Element {
        const { classes } = this.props;
        return (
            <div className={classes.root}>
                <Grid container={true} spacing={24}>
                    <Grid item={true} lg={3} xs={12} sm={6}>
                        <Paper className={classNames(classes.paper, classes.headerTiles)}>
                            <GroupIcon className={classes.headerTileIcon} />
                            <Typography className={classes.tileText}> {this.props.users.items.length} Customers</Typography>
                        </Paper>
                    </Grid>
                    <Grid item={true} lg={3} xs={12} sm={6}>
                        <Paper className={classNames(classes.paper, classes.headerTiles)}>
                            <MailIcon className={classes.headerTileIcon} />
                            <Typography className={classes.tileText}>Inbox</Typography>
                        </Paper>
                    </Grid>
                    <Grid item={true} lg={3} xs={12} sm={6}>
                        <Paper className={classNames(classes.paper, classes.headerTiles)}>
                            <BusinessIcon className={classes.headerTileIcon} />
                            <Typography className={classes.tileText}>Purchases</Typography>
                        </Paper>
                    </Grid>
                    <Grid item={true} lg={3} xs={12} sm={6}>
                        <Paper className={classNames(classes.paper, classes.headerTiles)}>
                            <SettingsIcon className={classes.headerTileIcon} />
                            <Typography className={classes.tileText}>Settings</Typography>
                        </Paper>
                    </Grid>
                    <Grid item={true} xs={12} md={6}>
                        {this.renderBarChart()}
                    </Grid>
                    <Grid item={true} xs={12} md={6}>
                        {this.renderRadialBarChart()}
                    </Grid>
                    <Grid item={true} xs={12}>
                        {this.renderUsers()}
                    </Grid>
                </Grid>
            </div>
        );
    }
}

const styles = (theme: Theme) => ({
    root: {
        flexGrow: 1,
        marginBottom: 24,
    },
    paper: {
        padding: theme.spacing.unit * 2,
        textAlign: 'center',
        color: theme.palette.text.secondary,
    },
    headerTiles: {
        overflowX: 'hidden',
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'center',
        borderRight: `5px solid ${theme.palette.secondary.main}`,
    },
    headerTileIcon: {
        fontSize: 40,
        color: theme.palette.primary.main,
        paddingRight: 5
    },
    tileText: {
        fontSize: 20,
        color: theme.palette.grey["400"],
    },
    sectionTitle: {
        paddingLeft: theme.spacing.unit * 2,
    },
    users: {
        marginBottom: 24,
        overflowX: 'scroll'
    },
    chart: {
        width: '100%'
    },
});

export default withStyles(styles as any)(HomePage as any) as any;

================================================
FILE: src/pages/account/Account.tsx
================================================
import * as React from 'react';
import { User } from '../../state/User';
import LoginPage from './Login';
import { Route, Switch } from 'react-router';
import { ProfilePage } from './Profile';
import { isAuthenticated } from '../../state/AppState';

interface IAccountProps {
    login?: (data: any) => void;
    match?: any;
    location?: any;
    classes?: any;
    user: User;
}

export class AccountPage extends React.Component<IAccountProps, {}> {
    private renderLogin = () => {
        return (
            <LoginPage
                user={this.props.user}
                login={this.props.login}
                match={this.props.match}
                location={this.props.location} />
        );
    }

    public render(): JSX.Element {
        return (<Switch>
            <Route path="/account" exact={true} component={isAuthenticated(ProfilePage as any)} />
            <Route path={'/account/login'} render={this.renderLogin} />
        </Switch>);
    }

}

================================================
FILE: src/pages/account/Login.tsx
================================================
import * as React from 'react';
import { Theme, withStyles, FormControl, InputLabel, Input, InputAdornment, Button, Icon } from '@material-ui/core';
import Paper from '@material-ui/core/Paper';
import * as querystring from 'querystring';
import { User } from '../../state/User';
import { Redirect } from 'react-router';

interface ILoginProps {
    login?: (data: any) => void;
    match?: any;
    location?: any;
    classes?: any;
    user: User;
}

interface ILoginState {
    email: string;
    password: string;
}

class LoginPage extends React.Component<ILoginProps, ILoginState> {
    public state = {
        email: "",
        password: ""
    };

    private handleEmailAddressChange = (event: any) => {
        this.setState({ email: event.target.value })
    }

    private handlePasswordChange = (event: any) => {
        this.setState({ password: event.target.value })
    }

    private handleLogin = () => {
        this.props.login(this.state);
    }

    public render(): JSX.Element {
        const classes = this.props.classes;

        if (this.props.user) {
            const path: string = querystring.
                parse((this.props.location.search as string).substr(1)).redirect as any || '/inbox';
            return <Redirect to={path} />
        }

        return (
            <div className={classes.container}>
                <Paper className={classes.paper}>
                    <h2>{'Login'}</h2>
                    <FormControl required={true} fullWidth={true} className={classes.field}>
                        <InputLabel htmlFor="email">Email Address</InputLabel>
                        <Input
                            value={this.state.email}
                            onChange={this.handleEmailAddressChange}
                            id="email"
                            startAdornment={
                                <InputAdornment position="start">
                                    <Icon>email</Icon>
                                </InputAdornment>}
                        />
                    </FormControl>
                    <FormControl required={true} fullWidth={true} className={classes.field}>
                        <InputLabel htmlFor="password">Password</InputLabel>
                        <Input
                            value={this.state.password}
                            onChange={this.handlePasswordChange}
                            type="password"
                            id="password"
                            startAdornment={
                                <InputAdornment position="start">
                                    <Icon>lock</Icon>
                                </InputAdornment>}
                        />
                    </FormControl>
                    <div className={classes.actions}>
                        <Button variant="raised" className={classes.button}>
                            Cancel
                        </Button>
                        <Button
                            onClick={this.handleLogin}
                            variant="raised"
                            color="primary"
                            className={classes.button}>
                            Submit
                        </Button>
                    </div>
                </Paper>
            </div>
        );
    }
}

const styles = (theme: Theme) => ({
    container: {
        display: 'flex',
        justifyContent: 'center'
    },
    paper: theme.mixins.gutters({
        paddingTop: 16,
        paddingBottom: 16,
        marginTop: theme.spacing.unit * 3,
        width: '30%',
        display: 'flex',
        flexDirection: 'column',
        alignContent: 'center',
        [theme.breakpoints.down('md')]: {
            width: '100%',
        },
    }),
    field: {
        marginTop: theme.spacing.unit * 3
    },
    actions: theme.mixins.gutters({
        paddingTop: 16,
        paddingBottom: 16,
        marginTop: theme.spacing.unit * 3,
        display: 'flex',
        flexDirection: 'row',
        alignContent: 'center'
    }),
    button: {
        marginRight: theme.spacing.unit
    },
});

export default withStyles(styles, { withTheme: true })(LoginPage as any) as any;



================================================
FILE: src/pages/account/Profile.tsx
================================================
import * as React from 'react';
import { Typography } from '@material-ui/core';

export class ProfilePage extends React.Component<{}, {}> {
    public render(): JSX.Element {
        return (<Typography noWrap={false}>{"Profile Page"}</Typography>)
    }
}

================================================
FILE: src/pages/mail/Drafts.tsx
================================================
import * as React from 'react'
import MailList from '../../components/MailList';
import { Paper, Typography, Theme, withStyles } from '@material-ui/core';
import { Button } from '@material-ui/core';

interface IDraftsProps {
    items: any[];
    classes: any;
}

class DraftsPage extends React.Component<IDraftsProps, {}> {

    public render(): JSX.Element {
        const { classes } = this.props;
        return (
            <Paper className={classes.root}>
                <div className={classes.boxHeader}>
                    <Typography className={classes.boxHeaderTitle}>Drafts</Typography>
                    <span className={classes.fillRemainingSpace}/>
                    <Button>Delete all</Button>
                </div>
                <MailList {...this.props} />
            </Paper>
        );
    }
}

const styles = (theme: Theme) => ({
    root: {
        width: '100%',
    },
    boxHeader: {
        width: '100%',
        display: 'flex',
        [theme.breakpoints.down('md')]: {
            flexDirection: 'column',
        },
    },
    boxHeaderTitle: {
        padding: '5px 10px',
        fontSize: 35,
    },
    fillRemainingSpace: {
        flex: '1 1 auto',
        [theme.breakpoints.down('md')]: {
            display: 'none',
        },
    },
});

export default withStyles(styles as any)(DraftsPage as any) as any;

================================================
FILE: src/pages/mail/Inbox.tsx
================================================
import * as React from 'react'
import MailList from '../../components/MailList';
import { Paper, Typography, Theme, withStyles } from '@material-ui/core';
import { Button } from '@material-ui/core';

interface InboxProps {
    items: any[];
    classes: any;
}

class InboxPage extends React.Component<InboxProps, {}> {

    public render(): JSX.Element {
        const { classes } = this.props;
        return (
            <Paper className={classes.root}>
                <div className={classes.boxHeader}>
                    <Typography className={classes.boxHeaderTitle}>Inbox</Typography>
                    <span className={classes.fillRemainingSpace}/>
                    <Button>Mark All As Read</Button>
                    <Button>Delete all</Button>
                </div>
                <MailList {...this.props} />
            </Paper>
        );
    }
}

const styles = (theme: Theme) => ({
    root: {
        width: '100%',
    },
    boxHeader: {
        width: '100%',
        display: 'flex',
        [theme.breakpoints.down('md')]: {
            flexDirection: 'column',
        },
    },
    boxHeaderTitle: {
        padding: '5px 10px',
        fontSize: 35,
    },
    fillRemainingSpace: {
        flex: '1 1 auto',
        [theme.breakpoints.down('md')]: {
            display: 'none',
        },
    },
});

export default withStyles(styles as any)(InboxPage as any) as any;

================================================
FILE: src/pages/mail/Mail.tsx
================================================
import * as React from 'react';
import { Route, Switch } from 'react-router';
import InboxPage from './Inbox';
import SentPage from './Sent';
import DraftsPage from './Drafts';

interface IMailProps {
    match?: any;
    location?: any;
    classes?: any;
    mail: any[];
}

export class MailPage extends React.Component<IMailProps, {}> {

    private renderInbox = () => {
        return (<InboxPage
            items={this.props.mail}
        />);
    }

    private renderSent = () => {
        return (<SentPage
            items={this.props.mail}
        />);
    }

    private renderDrafts = () => {
        return (<DraftsPage
            items={this.props.mail}
        />);
    }

    public render(): JSX.Element {
        return (
        <Switch>
            <Route path="/mail" exact={true} render={this.renderInbox} />
            <Route path="/mail/inbox" render={this.renderInbox} />
            <Route path="/mail/sent" render={this.renderSent} />
            <Route path="/mail/drafts" render={this.renderDrafts} />
        </Switch>);
    }

}

================================================
FILE: src/pages/mail/Sent.tsx
================================================
import * as React from 'react'
import MailList from '../../components/MailList';
import { Paper, Typography, Theme, withStyles } from '@material-ui/core';
import { Button } from '@material-ui/core';

interface ISentProps {
    items: any[];
    classes: any;
}

class SentPage extends React.Component<ISentProps, {}> {

    public render(): JSX.Element {
        const { classes } = this.props;
        return (
            <Paper className={classes.root}>
                <div className={classes.boxHeader}>
                    <Typography className={classes.boxHeaderTitle}>Sent</Typography>
                    <span className={classes.fillRemainingSpace}/>
                    <Button>Delete all</Button>
                </div>
                <MailList {...this.props} />
            </Paper>
        );
    }
}

const styles = (theme: Theme) => ({
    root: {
        width: '100%',
    },
    boxHeader: {
        width: '100%',
        display: 'flex',
        [theme.breakpoints.down('md')]: {
            flexDirection: 'column',
        },
    },
    boxHeaderTitle: {
        padding: '5px 10px',
        fontSize: 35,
    },
    fillRemainingSpace: {
        flex: '1 1 auto',
        [theme.breakpoints.down('md')]: {
            display: 'none',
        },
    },
});

export default withStyles(styles as any)(SentPage as any) as any;

================================================
FILE: src/reducers/AuthenticationReducer.ts
================================================
import { IAppAction, ActionType } from './../actions/Helpers';
import { User } from '../state/User';

export const AuthenticationReducer = (state: User = null, action: IAppAction): User => {
    switch (action.type) {
        case ActionType.LOGIN_REQUEST:
            return new User({email: action.payload.email, name: 'Goeme Nthomiwa', roles: ['Admin']});
        case ActionType.LOGOUT_REQUEST:
            return null;
        default:
            return state;
    }
};

================================================
FILE: src/reducers/CombinedReducers.ts
================================================
import { combineReducers } from "redux";
import { UtilityReducer } from './UtilityReducer';
import { AuthenticationReducer } from "./AuthenticationReducer";
import { rootReducer as usersReducers } from "../data/users";
import { rootReducer as materialsReducers } from "../data/material";
import { rootReducer as mailReducers } from "../data/mail";

export const reducers = combineReducers({
    utility: UtilityReducer,
    authentication: AuthenticationReducer,
    users: usersReducers,
    materials: materialsReducers,
    mail: mailReducers
});

================================================
FILE: src/reducers/UtilityReducer.ts
================================================
import { IAppAction, ActionType } from './../actions/Helpers';
import { Utility } from '../state/Utility';

export const UtilityReducer = (state: Utility = new Utility(), action: IAppAction): Utility => {
    switch (action.type) {
        case ActionType.OPEN_DRAWER:
            return state.set(Utility.DRAWER_OPEN, true) as Utility;
        case ActionType.CLOSE_DRAWER:
            return state.set(Utility.DRAWER_OPEN, false) as Utility;
        case ActionType.OPEN_ALERT:
            return state.set(Utility.ALERT, action.payload) as Utility;
        case ActionType.CLOSE_ALERT:
            return state.set(Utility.ALERT, null) as Utility;
        case ActionType.OPEN_SPINNER:
            return state.set(Utility.SPINNER, action.payload) as Utility;
        case ActionType.CLOSE_SPINNER:
            return state.set(Utility.SPINNER, null) as Utility;
        default:
            return state;
    }
};

================================================
FILE: src/registerServiceWorker.ts
================================================
// 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();
    });
  }
}


================================================
FILE: src/selectors/index.ts
================================================
import { AppState } from '../state/AppState';
import { createSelector } from 'reselect';
const randomColor = require('randomcolor');
import * as _ from 'lodash';
import * as moment from 'moment';

const materialItemsSelector = (state: AppState) => state.materials.items;
const mailSelector = (state: AppState) => state.mail;

export const getMaterialChartItems = createSelector(materialItemsSelector, (items: any[]) => {
    const categories = _.groupBy(items, x => x.category);
    const data = _.keys(categories).map(category => ({ name: category, value: categories[category].length, fill: randomColor() }));

    return data;
});

export const getMailitems = createSelector(mailSelector, (mail: any) => {
    return _.sortBy(mail.items.map((item: any) => 
    _.assign({}, item, {createdAt: moment(item.createdAt)}), (i: any) => i.createdAt));
});

================================================
FILE: src/spinner/Spinner.tsx
================================================
import * as React from 'react';
import Dialog from '@material-ui/core/Dialog';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import { withStyles, CircularProgress, WithStyles } from '@material-ui/core';

const styles = (theme: any) => ({
    progress: {
        margin: theme.spacing.unit * 2,
    },
    content: {
        display: 'flex',
        alignItems: 'center'
    }
});

interface ISpinnerProps {
    message?: string;
    classes?: any;
}

class SpinnerDialog extends React.Component<ISpinnerProps & WithStyles<"progress">, {}> {

    public render() {
        return (

            <Dialog
                open={this.props.message !== null}
                aria-labelledby="alert-dialog-title"
                aria-describedby="alert-dialog-description"
            >
                <DialogContent className={this.props.classes.content}>
                    <CircularProgress className={this.props.classes.progress} />
                    <DialogContentText id="alert-dialog-description">
                        {this.props.message}
                    </DialogContentText>
                </DialogContent>

            </Dialog>
        );
    }
}



export default withStyles(styles)(SpinnerDialog);


================================================
FILE: src/state/Alert.ts
================================================
import { Model } from "./Helpers";

interface IAlertButtonOptions {
    label: string;
    handler: () => void;
}

export interface IAlert {
    title?: string;
    message: string;
    buttons?: IAlertButtonOptions[];
}

export const AlertModel = Model<IAlert>({
    title: null,
    message: null,
    buttons: null
});

export class Alert extends AlertModel {
    public title: string;
    public message: string;
    public buttons: IAlertButtonOptions[];

    constructor(data: IAlert) {
        super(data);
    }
}

================================================
FILE: src/state/AppState.ts
================================================
import { connectedRouterRedirect } from 'redux-auth-wrapper/history4/redirect';
import { Utility } from './Utility';
import { Model } from "./Helpers";
import { User } from './User';

export interface IAppState {
    utility?: Utility;
    authentication?: User;
    users?: any;
    materials?: any;
    mail?: any;
}

export const AppStateModel = Model<IAppState>({
    utility: new Utility(),
    authentication: null,
    users: null,
    materials: null,
    mail: null
});

export class AppState extends AppStateModel {
    public static UTILITY = 'utility';
    public static AUTHENTICATION = "authentication";

    public utility: Utility;
    public authentication: User;
    public users: any;
    public materials: any;
    public mail: any;
}

export const isAuthenticated = connectedRouterRedirect({
    redirectPath: '/account/login',
    authenticatedSelector: (state: AppState) => state.authentication !== null,
    wrapperDisplayName: 'Authenticated'
}) as any;

================================================
FILE: src/state/Helpers.ts
================================================
import { Record } from 'immutable';

export const Model = <T>(data: T): Record.Class => {
    return Record(data);
};

================================================
FILE: src/state/Spinner.ts
================================================
import { Model } from "./Helpers";

export interface ISpinner {
    message: string;
}

export const SpinnerModel = Model<ISpinner>({
    message: null
});

export class Spinner extends SpinnerModel {
    public static MESSAGE = 'message';
    
    public message: string;
}

================================================
FILE: src/state/User.ts
================================================
import { Model } from "./Helpers";
import * as _ from 'lodash';

export interface IUser {
    email?: string;
    name?: string;
    roles?: string[];
}

const UserModel = Model<IUser>({
    email: null,
    name: null,
    roles: null
});

export class User extends UserModel {
    public static EMAIL = 'email';
    public static NAME = 'name';
    public static ROLES = 'roles';

    public email: string;
    public name: string;
    public roles: string[];

    public isInRole(candidate: string) {
        return _.intersection(this.roles, [candidate]).length > 0;
    }
}


================================================
FILE: src/state/Utility.ts
================================================
import { Model } from "./Helpers";
import { Alert } from './Alert';
import { Spinner } from "./Spinner";

export interface IUtility {
    drawerOpen?: boolean;
    alert?: Alert;
    spinner?: Spinner;
}

export const UtilityModel = Model<IUtility>({
    drawerOpen: false,
    alert: null,
    spinner: null
});

export class Utility extends UtilityModel {
    public static DRAWER_OPEN = 'drawerOpen';
    public static ALERT = 'alert';
    public static SPINNER = 'spinner';

    public drawerOpen: boolean;
    public alert: Alert;
    public spinner: Spinner;
}


================================================
FILE: src/store/Store.ts
================================================
import { reducers } from '../reducers/CombinedReducers';
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk';

export const store = createStore(reducers, applyMiddleware(thunk));

================================================
FILE: tsconfig.json
================================================
{
  "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": false,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  },
  "exclude": [
    "node_modules",
    "build",
    "scripts",
    "acceptance-tests",
    "webpack",
    "jest",
    "src/setupTests.ts"
  ]
}


================================================
FILE: tsconfig.prod.json
================================================
{
  "extends": "./tsconfig.json"
}

================================================
FILE: tsconfig.test.json
================================================
{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "commonjs"
  }
}

================================================
FILE: tslint.json
================================================
{
  "extends": ["tslint:recommended", "tslint-react", "tslint-config-prettier"],
  "linterOptions": {
    "exclude": [
      "config/**/*.js",
      "node_modules/**/*.ts"
    ]
  },
  "rules": {
    "ordered-imports": false,
    "member-ordering": false,
    "object-literal-sort-keys": false,
    "no-var-requires": false,
    "no-console": false,
    "jsx-no-lambda": false
  }
}
Download .txt
gitextract_wgb9fbz0/

├── .config/
│   └── tomahawkci.yml
├── .gitignore
├── Procfile
├── README.md
├── _config.yml
├── images.d.ts
├── package.json
├── public/
│   ├── index.html
│   └── manifest.json
├── server.js
├── src/
│   ├── App.css
│   ├── App.test.tsx
│   ├── App.tsx
│   ├── actions/
│   │   ├── App.Actions.ts
│   │   └── Helpers.ts
│   ├── alert/
│   │   └── Alert.tsx
│   ├── components/
│   │   ├── MailList.tsx
│   │   ├── TableHeader.tsx
│   │   └── TableToolbar.tsx
│   ├── data/
│   │   ├── mail.ts
│   │   ├── material.ts
│   │   └── users.ts
│   ├── index.css
│   ├── index.tsx
│   ├── navigation/
│   │   ├── App.Bar.tsx
│   │   ├── App.Drawer.tsx
│   │   └── styles.ts
│   ├── pages/
│   │   ├── Home.tsx
│   │   ├── account/
│   │   │   ├── Account.tsx
│   │   │   ├── Login.tsx
│   │   │   └── Profile.tsx
│   │   └── mail/
│   │       ├── Drafts.tsx
│   │       ├── Inbox.tsx
│   │       ├── Mail.tsx
│   │       └── Sent.tsx
│   ├── reducers/
│   │   ├── AuthenticationReducer.ts
│   │   ├── CombinedReducers.ts
│   │   └── UtilityReducer.ts
│   ├── registerServiceWorker.ts
│   ├── selectors/
│   │   └── index.ts
│   ├── spinner/
│   │   └── Spinner.tsx
│   ├── state/
│   │   ├── Alert.ts
│   │   ├── AppState.ts
│   │   ├── Helpers.ts
│   │   ├── Spinner.ts
│   │   ├── User.ts
│   │   └── Utility.ts
│   └── store/
│       └── Store.ts
├── tsconfig.json
├── tsconfig.prod.json
├── tsconfig.test.json
└── tslint.json
Download .txt
SYMBOL INDEX (80 symbols across 24 files)

FILE: src/App.tsx
  class App (line 17) | class App extends React.Component {
    method render (line 18) | public render() {

FILE: src/actions/App.Actions.ts
  type IApplicationProps (line 8) | interface IApplicationProps {

FILE: src/actions/Helpers.ts
  type ActionType (line 3) | enum ActionType {
  type IAppAction (line 18) | interface IAppAction extends Action<ActionType> {

FILE: src/alert/Alert.tsx
  type IAlertProps (line 10) | interface IAlertProps {
  class AlertDialog (line 15) | class AlertDialog extends React.Component<IAlertProps, {}> {
    method render (line 21) | public render() {

FILE: src/components/MailList.tsx
  type IMailListProps (line 38) | interface IMailListProps {
  type IState (line 43) | interface IState {
  class MailList (line 47) | class MailList extends React.Component<IMailListProps, IState> {
    method render (line 58) | public render() {

FILE: src/components/TableHeader.tsx
  type IColumnData (line 4) | interface IColumnData {
  type IEnhancedTableHeadProps (line 11) | interface IEnhancedTableHeadProps {
  class EnhancedTableHead (line 21) | class EnhancedTableHead extends React.Component<IEnhancedTableHeadProps,...
    method render (line 26) | public render() {

FILE: src/components/TableToolbar.tsx
  type IEnhancedTableToolbarProps (line 7) | interface IEnhancedTableToolbarProps {
  class EnhancedTableToolbar (line 12) | class EnhancedTableToolbar extends React.Component<IEnhancedTableToolbar...
    method render (line 14) | public render(): JSX.Element {

FILE: src/navigation/App.Bar.tsx
  type IAppProps (line 35) | interface IAppProps extends IApplicationProps {
  type IState (line 40) | interface IState {
  class MiniDrawer (line 45) | class MiniDrawer extends React.Component<IAppProps, IState> {
    method componentWillMount (line 52) | public componentWillMount() {
    method renderAlert (line 105) | private renderAlert(): JSX.Element {
    method renderSpinner (line 118) | private renderSpinner(): JSX.Element {
    method renderNotifications (line 130) | private renderNotifications(notifications: any[]) {
    method renderAppBar (line 158) | private renderAppBar() {
    method renderDrawer (line 235) | private renderDrawer() {
    method render (line 248) | public render() {

FILE: src/navigation/App.Drawer.tsx
  type IAppDrawer (line 16) | interface IAppDrawer {
  class AppDrawer (line 24) | class AppDrawer extends React.Component<IAppDrawer, {}> {
    method render (line 33) | public render(): JSX.Element {

FILE: src/pages/Home.tsx
  type IDashboardProps (line 13) | interface IDashboardProps {
  type IPageState (line 22) | interface IPageState {
  class HomePage (line 27) | class HomePage extends React.Component<IDashboardProps, IPageState> {
    method renderUsers (line 43) | private renderUsers(): JSX.Element {
    method renderRadialBarChart (line 94) | private renderRadialBarChart(): JSX.Element {
    method renderBarChart (line 115) | private renderBarChart(): JSX.Element {
    method render (line 132) | public render(): JSX.Element {

FILE: src/pages/account/Account.tsx
  type IAccountProps (line 8) | interface IAccountProps {
  class AccountPage (line 16) | class AccountPage extends React.Component<IAccountProps, {}> {
    method render (line 27) | public render(): JSX.Element {

FILE: src/pages/account/Login.tsx
  type ILoginProps (line 8) | interface ILoginProps {
  type ILoginState (line 16) | interface ILoginState {
  class LoginPage (line 21) | class LoginPage extends React.Component<ILoginProps, ILoginState> {
    method render (line 39) | public render(): JSX.Element {

FILE: src/pages/account/Profile.tsx
  class ProfilePage (line 4) | class ProfilePage extends React.Component<{}, {}> {
    method render (line 5) | public render(): JSX.Element {

FILE: src/pages/mail/Drafts.tsx
  type IDraftsProps (line 6) | interface IDraftsProps {
  class DraftsPage (line 11) | class DraftsPage extends React.Component<IDraftsProps, {}> {
    method render (line 13) | public render(): JSX.Element {

FILE: src/pages/mail/Inbox.tsx
  type InboxProps (line 6) | interface InboxProps {
  class InboxPage (line 11) | class InboxPage extends React.Component<InboxProps, {}> {
    method render (line 13) | public render(): JSX.Element {

FILE: src/pages/mail/Mail.tsx
  type IMailProps (line 7) | interface IMailProps {
  class MailPage (line 14) | class MailPage extends React.Component<IMailProps, {}> {
    method render (line 34) | public render(): JSX.Element {

FILE: src/pages/mail/Sent.tsx
  type ISentProps (line 6) | interface ISentProps {
  class SentPage (line 11) | class SentPage extends React.Component<ISentProps, {}> {
    method render (line 13) | public render(): JSX.Element {

FILE: src/registerServiceWorker.ts
  function register (line 22) | function register() {
  function registerValidSW (line 59) | function registerValidSW(swUrl: string) {
  function checkValidServiceWorker (line 90) | function checkValidServiceWorker(swUrl: string) {
  function unregister (line 117) | function unregister() {

FILE: src/spinner/Spinner.tsx
  type ISpinnerProps (line 17) | interface ISpinnerProps {
  class SpinnerDialog (line 22) | class SpinnerDialog extends React.Component<ISpinnerProps & WithStyles<"...
    method render (line 24) | public render() {

FILE: src/state/Alert.ts
  type IAlertButtonOptions (line 3) | interface IAlertButtonOptions {
  type IAlert (line 8) | interface IAlert {
  class Alert (line 20) | class Alert extends AlertModel {
    method constructor (line 25) | constructor(data: IAlert) {

FILE: src/state/AppState.ts
  type IAppState (line 6) | interface IAppState {
  class AppState (line 22) | class AppState extends AppStateModel {

FILE: src/state/Spinner.ts
  type ISpinner (line 3) | interface ISpinner {
  class Spinner (line 11) | class Spinner extends SpinnerModel {

FILE: src/state/User.ts
  type IUser (line 4) | interface IUser {
  class User (line 16) | class User extends UserModel {
    method isInRole (line 25) | public isInRole(candidate: string) {

FILE: src/state/Utility.ts
  type IUtility (line 5) | interface IUtility {
  class Utility (line 17) | class Utility extends UtilityModel {
Condensed preview — 52 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (72K chars).
[
  {
    "path": ".config/tomahawkci.yml",
    "chars": 99,
    "preview": "version: '1.0.0'\n\ndependencies:\n  - npm install --ignore-scripts\n\ntasks:\n  test:\n    - npm run test"
  },
  {
    "path": ".gitignore",
    "chars": 257,
    "preview": "# dependencies\n/node_modules\n\n# testing\n/coverage\n\n# production\n/build\n\n# misc\n.DS_Store\n.env.local\n.env.development.loc"
  },
  {
    "path": "Procfile",
    "chars": 19,
    "preview": "web: npm run deploy"
  },
  {
    "path": "README.md",
    "chars": 973,
    "preview": "## Description\nThis is a boilerplate for React using Typescript, Material UI and Redux, React Router.\n\n## Demo\n*Visit [D"
  },
  {
    "path": "_config.yml",
    "chars": 26,
    "preview": "theme: jekyll-theme-cayman"
  },
  {
    "path": "images.d.ts",
    "chars": 69,
    "preview": "declare module '*.svg'\ndeclare module '*.png'\ndeclare module '*.jpg'\n"
  },
  {
    "path": "package.json",
    "chars": 1836,
    "preview": "{\n  \"name\": \"react-boilerplate\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"dependencies\": {\n    \"@material-ui/core\": \""
  },
  {
    "path": "public/index.html",
    "chars": 1775,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-wid"
  },
  {
    "path": "public/manifest.json",
    "chars": 317,
    "preview": "{\n  \"short_name\": \"React App\",\n  \"name\": \"Create React App Sample\",\n  \"icons\": [\n    {\n      \"src\": \"favicon.ico\",\n     "
  },
  {
    "path": "server.js",
    "chars": 285,
    "preview": "const express = require('express');\nconst path = require('path');\nconst app = express();\n\napp.use(express.static(path.jo"
  },
  {
    "path": "src/App.css",
    "chars": 377,
    "preview": ".App {\n  text-align: center;\n}\n\n.App-logo {\n  animation: App-logo-spin infinite 20s linear;\n  height: 80px;\n}\n\n.App-head"
  },
  {
    "path": "src/App.test.tsx",
    "chars": 258,
    "preview": "import * as React from 'react';\nimport * as ReactDOM from 'react-dom';\nimport App from './App';\n\nit('renders without cra"
  },
  {
    "path": "src/App.tsx",
    "chars": 783,
    "preview": "import * as React from 'react';\nimport './App.css';\nimport AppNavBar from './navigation/App.Bar';\nimport { BrowserRouter"
  },
  {
    "path": "src/actions/App.Actions.ts",
    "chars": 2326,
    "preview": "import { IAppAction, ActionType } from './Helpers';\nimport { match } from 'react-router';\nimport { Utility } from '../st"
  },
  {
    "path": "src/actions/Helpers.ts",
    "chars": 353,
    "preview": "import { Action } from \"redux\";\n\nexport enum ActionType {\n    OPEN_DRAWER,\n    CLOSE_DRAWER,\n    OPEN_ALERT,\n    CLOSE_A"
  },
  {
    "path": "src/alert/Alert.tsx",
    "chars": 1611,
    "preview": "import * as React from 'react';\nimport Button from '@material-ui/core/Button';\nimport Dialog from '@material-ui/core/Dia"
  },
  {
    "path": "src/components/MailList.tsx",
    "chars": 3206,
    "preview": "import * as React from 'react';\nimport { withStyles, Theme } from '@material-ui/core/styles';\nimport ExpansionPanel from"
  },
  {
    "path": "src/components/TableHeader.tsx",
    "chars": 2541,
    "preview": "import * as React from 'react';\nimport { TableHead, TableRow, TableCell, Checkbox, Tooltip, TableSortLabel } from '@mate"
  },
  {
    "path": "src/components/TableToolbar.tsx",
    "chars": 2638,
    "preview": "import * as React from 'react';\nimport { Toolbar, Typography, Tooltip, IconButton, Theme, withStyles } from '@material-u"
  },
  {
    "path": "src/data/mail.ts",
    "chars": 211,
    "preview": "const Resourcer = require('redux-rest-resource');\n\nexport const { types, actions, rootReducer } = Resourcer.createResour"
  },
  {
    "path": "src/data/material.ts",
    "chars": 220,
    "preview": "const Resourcer = require('redux-rest-resource');\n\nexport const { types, actions, rootReducer } = Resourcer.createResour"
  },
  {
    "path": "src/data/users.ts",
    "chars": 212,
    "preview": "const Resourcer = require('redux-rest-resource');\n\nexport const { types, actions, rootReducer } = Resourcer.createResour"
  },
  {
    "path": "src/index.css",
    "chars": 63,
    "preview": "body {\n  margin: 0;\n  padding: 0;\n  font-family: sans-serif;\n}\n"
  },
  {
    "path": "src/index.tsx",
    "chars": 284,
    "preview": "import * as React from 'react';\nimport * as ReactDOM from 'react-dom';\nimport App from './App';\nimport './index.css';\nim"
  },
  {
    "path": "src/navigation/App.Bar.tsx",
    "chars": 9084,
    "preview": "//#region \nimport * as React from 'react';\nconst classNames = require('classnames');\nimport { withStyles } from '@materi"
  },
  {
    "path": "src/navigation/App.Drawer.tsx",
    "chars": 2876,
    "preview": "import * as React from 'react';\nimport InboxIcon from '@material-ui/icons/Inbox';\nimport DraftsIcon from '@material-ui/i"
  },
  {
    "path": "src/navigation/styles.ts",
    "chars": 2393,
    "preview": "import { Theme } from \"@material-ui/core\";\n\nconst drawerWidth = 240;\n\nexport const styles = (theme: Theme) => ({\n    roo"
  },
  {
    "path": "src/pages/Home.tsx",
    "chars": 8096,
    "preview": "import * as React from 'react';\nimport {\n    Theme, withStyles, Paper, Table, TableHead, TableRow,\n    TableCell, TableB"
  },
  {
    "path": "src/pages/account/Account.tsx",
    "chars": 976,
    "preview": "import * as React from 'react';\nimport { User } from '../../state/User';\nimport LoginPage from './Login';\nimport { Route"
  },
  {
    "path": "src/pages/account/Login.tsx",
    "chars": 4236,
    "preview": "import * as React from 'react';\nimport { Theme, withStyles, FormControl, InputLabel, Input, InputAdornment, Button, Icon"
  },
  {
    "path": "src/pages/account/Profile.tsx",
    "chars": 256,
    "preview": "import * as React from 'react';\nimport { Typography } from '@material-ui/core';\n\nexport class ProfilePage extends React."
  },
  {
    "path": "src/pages/mail/Drafts.tsx",
    "chars": 1359,
    "preview": "import * as React from 'react'\nimport MailList from '../../components/MailList';\nimport { Paper, Typography, Theme, with"
  },
  {
    "path": "src/pages/mail/Inbox.tsx",
    "chars": 1406,
    "preview": "import * as React from 'react'\nimport MailList from '../../components/MailList';\nimport { Paper, Typography, Theme, with"
  },
  {
    "path": "src/pages/mail/Mail.tsx",
    "chars": 1065,
    "preview": "import * as React from 'react';\nimport { Route, Switch } from 'react-router';\nimport InboxPage from './Inbox';\nimport Se"
  },
  {
    "path": "src/pages/mail/Sent.tsx",
    "chars": 1349,
    "preview": "import * as React from 'react'\nimport MailList from '../../components/MailList';\nimport { Paper, Typography, Theme, with"
  },
  {
    "path": "src/reducers/AuthenticationReducer.ts",
    "chars": 475,
    "preview": "import { IAppAction, ActionType } from './../actions/Helpers';\nimport { User } from '../state/User';\n\nexport const Authe"
  },
  {
    "path": "src/reducers/CombinedReducers.ts",
    "chars": 549,
    "preview": "import { combineReducers } from \"redux\";\nimport { UtilityReducer } from './UtilityReducer';\nimport { AuthenticationReduc"
  },
  {
    "path": "src/reducers/UtilityReducer.ts",
    "chars": 917,
    "preview": "import { IAppAction, ActionType } from './../actions/Helpers';\nimport { Utility } from '../state/Utility';\n\nexport const"
  },
  {
    "path": "src/registerServiceWorker.ts",
    "chars": 4534,
    "preview": "// tslint:disable:no-console\n// In production, we register a service worker to serve assets from local cache.\n\n// This l"
  },
  {
    "path": "src/selectors/index.ts",
    "chars": 850,
    "preview": "import { AppState } from '../state/AppState';\nimport { createSelector } from 'reselect';\nconst randomColor = require('ra"
  },
  {
    "path": "src/spinner/Spinner.tsx",
    "chars": 1300,
    "preview": "import * as React from 'react';\nimport Dialog from '@material-ui/core/Dialog';\nimport DialogContent from '@material-ui/c"
  },
  {
    "path": "src/state/Alert.ts",
    "chars": 521,
    "preview": "import { Model } from \"./Helpers\";\n\ninterface IAlertButtonOptions {\n    label: string;\n    handler: () => void;\n}\n\nexpor"
  },
  {
    "path": "src/state/AppState.ts",
    "chars": 978,
    "preview": "import { connectedRouterRedirect } from 'redux-auth-wrapper/history4/redirect';\nimport { Utility } from './Utility';\nimp"
  },
  {
    "path": "src/state/Helpers.ts",
    "chars": 117,
    "preview": "import { Record } from 'immutable';\n\nexport const Model = <T>(data: T): Record.Class => {\n    return Record(data);\n};"
  },
  {
    "path": "src/state/Spinner.ts",
    "chars": 274,
    "preview": "import { Model } from \"./Helpers\";\n\nexport interface ISpinner {\n    message: string;\n}\n\nexport const SpinnerModel = Mode"
  },
  {
    "path": "src/state/User.ts",
    "chars": 579,
    "preview": "import { Model } from \"./Helpers\";\nimport * as _ from 'lodash';\n\nexport interface IUser {\n    email?: string;\n    name?:"
  },
  {
    "path": "src/state/Utility.ts",
    "chars": 567,
    "preview": "import { Model } from \"./Helpers\";\nimport { Alert } from './Alert';\nimport { Spinner } from \"./Spinner\";\n\nexport interfa"
  },
  {
    "path": "src/store/Store.ts",
    "chars": 211,
    "preview": "import { reducers } from '../reducers/CombinedReducers';\nimport { createStore, applyMiddleware } from 'redux'\nimport thu"
  },
  {
    "path": "tsconfig.json",
    "chars": 717,
    "preview": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"outDir\": \"build/dist\",\n    \"module\": \"esnext\",\n    \"target\": \"es5\",\n  "
  },
  {
    "path": "tsconfig.prod.json",
    "chars": 34,
    "preview": "{\n  \"extends\": \"./tsconfig.json\"\n}"
  },
  {
    "path": "tsconfig.test.json",
    "chars": 87,
    "preview": "{\n  \"extends\": \"./tsconfig.json\",\n  \"compilerOptions\": {\n    \"module\": \"commonjs\"\n  }\n}"
  },
  {
    "path": "tslint.json",
    "chars": 383,
    "preview": "{\n  \"extends\": [\"tslint:recommended\", \"tslint-react\", \"tslint-config-prettier\"],\n  \"linterOptions\": {\n    \"exclude\": [\n "
  }
]

About this extraction

This page contains the full source code of the goemen/react-material-ui-typescript GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 52 files (65.4 KB), approximately 16.0k tokens, and a symbol index with 80 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!