Added Navbar
This commit is contained in:
		@@ -26,6 +26,7 @@
 | 
				
			|||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <None Remove="ClientApp\src\common\components\BirdmapTitle.tsx" />
 | 
				
			||||||
    <None Remove="ClientApp\src\common\ErrorDispatcher.ts" />
 | 
					    <None Remove="ClientApp\src\common\ErrorDispatcher.ts" />
 | 
				
			||||||
    <None Remove="ClientApp\src\common\ServiceBase.ts" />
 | 
					    <None Remove="ClientApp\src\common\ServiceBase.ts" />
 | 
				
			||||||
    <None Remove="ClientApp\src\components\auth\Auth.tsx" />
 | 
					    <None Remove="ClientApp\src\components\auth\Auth.tsx" />
 | 
				
			||||||
@@ -34,6 +35,13 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  <ItemGroup>
 | 
					  <ItemGroup>
 | 
				
			||||||
    <TypeScriptCompile Include="ClientApp\src\components\auth\Auth.tsx" />
 | 
					    <TypeScriptCompile Include="ClientApp\src\components\auth\Auth.tsx" />
 | 
				
			||||||
 | 
						<TypeScriptCompile Include="ClientApp\src\common\components\BirdmapTitle.tsx" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <Folder Include="ClientApp\src\components\dashboard\" />
 | 
				
			||||||
 | 
					    <Folder Include="ClientApp\src\components\devices\" />
 | 
				
			||||||
 | 
					    <Folder Include="ClientApp\src\components\heatmap\" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
 | 
					  <Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										12
									
								
								Birdmap/ClientApp/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										12
									
								
								Birdmap/ClientApp/package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -1444,9 +1444,9 @@
 | 
				
			|||||||
      },
 | 
					      },
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "csstype": {
 | 
					        "csstype": {
 | 
				
			||||||
          "version": "3.0.3",
 | 
					          "version": "3.0.4",
 | 
				
			||||||
          "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.3.tgz",
 | 
					          "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.4.tgz",
 | 
				
			||||||
          "integrity": "sha512-jPl+wbWPOWJ7SXsWyqGRk3lGecbar0Cb0OvZF/r/ZU011R4YqiRehgkQ9p4eQfo9DSDLqLL3wHwfxeJiuIsNag=="
 | 
					          "integrity": "sha512-xc8DUsCLmjvCfoD7LTGE0ou2MIWLx0K9RCZwSHMOdynqRsP4MtUcLeqh1HcQ2dInwDTqn+3CE0/FZh1et+p4jA=="
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        "dom-helpers": {
 | 
					        "dom-helpers": {
 | 
				
			||||||
          "version": "5.2.0",
 | 
					          "version": "5.2.0",
 | 
				
			||||||
@@ -7933,9 +7933,9 @@
 | 
				
			|||||||
      },
 | 
					      },
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "csstype": {
 | 
					        "csstype": {
 | 
				
			||||||
          "version": "3.0.3",
 | 
					          "version": "3.0.4",
 | 
				
			||||||
          "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.3.tgz",
 | 
					          "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.4.tgz",
 | 
				
			||||||
          "integrity": "sha512-jPl+wbWPOWJ7SXsWyqGRk3lGecbar0Cb0OvZF/r/ZU011R4YqiRehgkQ9p4eQfo9DSDLqLL3wHwfxeJiuIsNag=="
 | 
					          "integrity": "sha512-xc8DUsCLmjvCfoD7LTGE0ou2MIWLx0K9RCZwSHMOdynqRsP4MtUcLeqh1HcQ2dInwDTqn+3CE0/FZh1et+p4jA=="
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,45 +1,63 @@
 | 
				
			|||||||
import { Box, Container } from '@material-ui/core';
 | 
					import { Box, Container } from '@material-ui/core';
 | 
				
			||||||
import AppBar from '@material-ui/core/AppBar';
 | 
					import AppBar from '@material-ui/core/AppBar';
 | 
				
			||||||
import blue from '@material-ui/core/colors/blue';
 | 
					import blue from '@material-ui/core/colors/blue';
 | 
				
			||||||
import { createMuiTheme } from '@material-ui/core/styles';
 | 
					import orange from '@material-ui/core/colors/orange';
 | 
				
			||||||
 | 
					import { createMuiTheme, createStyles, makeStyles, Theme } from '@material-ui/core/styles';
 | 
				
			||||||
import Toolbar from '@material-ui/core/Toolbar';
 | 
					import Toolbar from '@material-ui/core/Toolbar';
 | 
				
			||||||
import Typography from '@material-ui/core/Typography';
 | 
					import Typography from '@material-ui/core/Typography';
 | 
				
			||||||
import { ThemeProvider } from '@material-ui/styles';
 | 
					import { ThemeProvider } from '@material-ui/styles';
 | 
				
			||||||
import React, { useState } from 'react';
 | 
					import React, { useState } from 'react';
 | 
				
			||||||
import { BrowserRouter, NavLink, Redirect, Route, Switch } from 'react-router-dom';
 | 
					import { BrowserRouter, NavLink, Redirect, Route, Switch } from 'react-router-dom';
 | 
				
			||||||
 | 
					import BirdmapTitle from './common/components/BirdmapTitle';
 | 
				
			||||||
import Auth from './components/auth/Auth';
 | 
					import Auth from './components/auth/Auth';
 | 
				
			||||||
import AuthService from './components/auth/AuthService';
 | 
					import AuthService from './components/auth/AuthService';
 | 
				
			||||||
import Home from './components/Home';
 | 
					 | 
				
			||||||
import './custom.css';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const theme = createMuiTheme({
 | 
					const theme = createMuiTheme({
 | 
				
			||||||
    palette: {
 | 
					    palette: {
 | 
				
			||||||
        primary: {
 | 
					        primary: {
 | 
				
			||||||
            main: blue[800]
 | 
					            main: blue[900],
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					        secondary: {
 | 
				
			||||||
 | 
					            main: orange[200],
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function App() {
 | 
					function App() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const [authenticated, setAuthenticated] = useState(AuthService.isAuthenticated());
 | 
					    const [authenticated, setAuthenticated] = useState(AuthService.isAuthenticated());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const onAuthenticated = () => {
 | 
					    const onAuthenticated = () => {
 | 
				
			||||||
        setAuthenticated(AuthService.isAuthenticated());
 | 
					        setAuthenticated(AuthService.isAuthenticated());
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const LoginComponent = () => {
 | 
					    const AuthComponent = () => {
 | 
				
			||||||
        return (
 | 
					        return (
 | 
				
			||||||
            <Auth onAuthenticated={onAuthenticated} />
 | 
					            <Auth onAuthenticated={onAuthenticated} />
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const DashboardComponent = () => {
 | 
				
			||||||
 | 
					        return <Typography>Dashboard</Typography>;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const DevicesComponent = () => {
 | 
				
			||||||
 | 
					        return <Typography>Devices</Typography>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    const HeatmapComponent = () => {
 | 
				
			||||||
 | 
					        return <Typography>Heatmap</Typography>;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <ThemeProvider theme={theme}>
 | 
					        <ThemeProvider theme={theme}>
 | 
				
			||||||
                <BrowserRouter>
 | 
					                <BrowserRouter>
 | 
				
			||||||
                    <Switch>
 | 
					                    <Switch>
 | 
				
			||||||
                        <PublicRoute path="/login" component={LoginComponent} />
 | 
					                        <PublicRoute path="/login" component={AuthComponent} />
 | 
				
			||||||
                        <PrivateRoute path="/" exact authenticated={authenticated} component={Home} />
 | 
					                        <PrivateRoute path="/" exact authenticated={authenticated} component={DashboardComponent} />
 | 
				
			||||||
 | 
					                        <PrivateRoute path="/devices" exact authenticated={authenticated} component={DevicesComponent} />
 | 
				
			||||||
 | 
					                        <PrivateRoute path="/heatmap" exact authenticated={authenticated} component={HeatmapComponent} />
 | 
				
			||||||
                    </Switch>
 | 
					                    </Switch>
 | 
				
			||||||
                </BrowserRouter>
 | 
					                </BrowserRouter>
 | 
				
			||||||
        </ThemeProvider>
 | 
					        </ThemeProvider>
 | 
				
			||||||
@@ -51,7 +69,7 @@ export default App;
 | 
				
			|||||||
const PublicRoute = ({ component: Component, ...rest }: { [x: string]: any, component: any}) => {
 | 
					const PublicRoute = ({ component: Component, ...rest }: { [x: string]: any, component: any}) => {
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <Route {...rest} render={matchProps => (
 | 
					        <Route {...rest} render={matchProps => (
 | 
				
			||||||
            <NoLayout component={Component} {...matchProps} />
 | 
					            <DefaultLayout component={Component} authenticated={false} {...matchProps} />
 | 
				
			||||||
        )} />
 | 
					        )} />
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -60,28 +78,32 @@ const PrivateRoute = ({ component: Component, authenticated: Authenticated, ...r
 | 
				
			|||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <Route {...rest} render={matchProps => (
 | 
					        <Route {...rest} render={matchProps => (
 | 
				
			||||||
            Authenticated
 | 
					            Authenticated
 | 
				
			||||||
                ? <DefaultLayout component={Component} {...matchProps} />
 | 
					                ? <DefaultLayout component={Component} authenticated={Authenticated} {...matchProps} />
 | 
				
			||||||
                : <Redirect to='/login' />
 | 
					                : <Redirect to='/login' />
 | 
				
			||||||
        )} />
 | 
					        )} />
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const NoLayout = ({ component: Component, ...rest }: { [x: string]: any, component: any }) => {
 | 
					const DefaultLayout = ({ component: Component, authenticated: Authenticated, ...rest }: { [x: string]: any, component: any, authenticated: any }) => {
 | 
				
			||||||
    return (
 | 
					    const classes = useDefaultLayoutStyles();
 | 
				
			||||||
        <Component {...rest} />
 | 
					
 | 
				
			||||||
    );
 | 
					    const renderNavLinks = () => {
 | 
				
			||||||
};
 | 
					        return Authenticated
 | 
				
			||||||
 | 
					            ? <Container className={classes.nav_menu}>
 | 
				
			||||||
 | 
					                <NavLink exact to="/" className={classes.nav_menu_item} activeClassName={classes.nav_menu_item_active}>Dashboard</NavLink>
 | 
				
			||||||
 | 
					                <NavLink exact to="/devices" className={classes.nav_menu_item} activeClassName={classes.nav_menu_item_active}>Devices</NavLink>
 | 
				
			||||||
 | 
					                <NavLink exact to="/heatmap" className={classes.nav_menu_item} activeClassName={classes.nav_menu_item_active}>Heatmap</NavLink>
 | 
				
			||||||
 | 
					            </Container>
 | 
				
			||||||
 | 
					            : null;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const DefaultLayout = ({ component: Component, ...rest }: { [x: string]: any, component: any }) => {
 | 
					 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <React.Fragment>
 | 
					        <React.Fragment>
 | 
				
			||||||
            <AppBar position="static">
 | 
					            <AppBar position="static">
 | 
				
			||||||
                <Toolbar>
 | 
					                <Toolbar>
 | 
				
			||||||
                    <Typography component={'span'}>
 | 
					                    <BirdmapTitle />
 | 
				
			||||||
                        <Container className="nav-menu">
 | 
					                    <Typography component={'span'} className={classes.typo}>
 | 
				
			||||||
                            <NavLink exact to="/" className="nav-menu-item" activeStyle={{ color: 'white' }}>Dashboard</NavLink>
 | 
					                        {renderNavLinks()}
 | 
				
			||||||
                            <NavLink exact to="/login" className="nav-menu-item" activeStyle={{ color: 'white' }}>Login</NavLink>
 | 
					 | 
				
			||||||
                        </Container>
 | 
					 | 
				
			||||||
                    </Typography>
 | 
					                    </Typography>
 | 
				
			||||||
                </Toolbar>
 | 
					                </Toolbar>
 | 
				
			||||||
            </AppBar>
 | 
					            </AppBar>
 | 
				
			||||||
@@ -90,4 +112,35 @@ const DefaultLayout = ({ component: Component, ...rest }: { [x: string]: any, co
 | 
				
			|||||||
            </Box>
 | 
					            </Box>
 | 
				
			||||||
        </React.Fragment>
 | 
					        </React.Fragment>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const useDefaultLayoutStyles = makeStyles((theme: Theme) =>
 | 
				
			||||||
 | 
					    createStyles({
 | 
				
			||||||
 | 
					        typo: {
 | 
				
			||||||
 | 
					            marginLeft: 'auto',
 | 
				
			||||||
 | 
					            color: 'white',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        nav_menu: {
 | 
				
			||||||
 | 
					            display: 'flex',
 | 
				
			||||||
 | 
					            flexDirection: 'row',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        nav_menu_item: {
 | 
				
			||||||
 | 
					            textDecoration: 'none',
 | 
				
			||||||
 | 
					            fontWeight: 'normal',
 | 
				
			||||||
 | 
					            color: 'inherit',
 | 
				
			||||||
 | 
					            marginLeft: '24px',
 | 
				
			||||||
 | 
					            '&:hover': {
 | 
				
			||||||
 | 
					                color: 'inherit',
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        nav_menu_item_active: {
 | 
				
			||||||
 | 
					            textDecoration: 'underline',
 | 
				
			||||||
 | 
					            fontWeight: 'bold',
 | 
				
			||||||
 | 
					            color: 'inherit',
 | 
				
			||||||
 | 
					            marginLeft: '24px',
 | 
				
			||||||
 | 
					            '&:hover': {
 | 
				
			||||||
 | 
					                color: 'inherit',
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    }),
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
@@ -1 +1 @@
 | 
				
			|||||||
{"version":3,"file":"ServiceBase.js","sourceRoot":"","sources":["ServiceBase.ts"],"names":[],"mappings":";;AAAA,qDAAgD;AAEhD,SAAS,GAAG,CAAC,GAAG;IACZ,IAAI,OAAO,GAAG;QACV,MAAM,EAAE,KAAK;QACb,OAAO,EAAE;YACL,cAAc,EAAE,kBAAkB;YAClC,eAAe,EAAE,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC;SAClD;KACJ,CAAC;IAEF,OAAO,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,IAAI,CAAC,GAAG,EAAE,OAAO;IACtB,IAAI,OAAO,GAAG;QACV,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACL,cAAc,EAAE,kBAAkB;YAClC,eAAe,EAAE,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC;SAClD;QACD,IAAI,EAAE,EAAE;KACX,CAAC;IAEF,IAAI,OAAO;QACP,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAE3C,OAAO,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,WAAW,CAAC,GAAG,EAAE,OAAO;IAC7B,OAAO,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC;SACrB,IAAI,CAAC,qBAAqB,CAAC;SAC3B,KAAK,CAAC,YAAY,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAQ;IACnC,IAAI,CAAC,QAAQ,CAAC,EAAE;QACZ,OAAO,QAAQ,CAAC,IAAI,EAAE;aACjB,IAAI,CAAC,UAAA,IAAI,IAAI,OAAA,YAAY,CAAC,IAAI,CAAC,EAAlB,CAAkB,CAAC,CAAC;IAE1C,OAAO,QAAQ,CAAC,IAAI,EAAE;SACjB,IAAI,CAAC,UAAA,IAAI,IAAI,OAAA,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,EAAnC,CAAmC,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,YAAY,CAAC,QAAQ;IAC1B,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAEtB,IAAI,QAAQ,IAAI,QAAQ,CAAC,KAAK;QAC1B,yBAAe,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE/C,OAAO,OAAO,CAAC,MAAM,EAAE,CAAC;AAC5B,CAAC;AAED,kBAAe;IACX,GAAG,KAAA;IACH,IAAI,MAAA;IACJ,WAAW,aAAA;CACd,CAAC"}
 | 
					{"version":3,"file":"ServiceBase.js","sourceRoot":"","sources":["ServiceBase.ts"],"names":[],"mappings":";;AAAA,qDAAgD;AAEhD,SAAS,GAAG,CAAC,GAAW;IACpB,IAAI,OAAO,GAAG;QACV,MAAM,EAAE,KAAK;QACb,OAAO,EAAE;YACL,cAAc,EAAE,kBAAkB;YAClC,eAAe,EAAE,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC;SAClD;KACJ,CAAC;IAEF,OAAO,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,IAAI,CAAC,GAAW,EAAE,OAAY;IACnC,IAAI,OAAO,GAAG;QACV,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACL,cAAc,EAAE,kBAAkB;YAClC,eAAe,EAAE,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC;SAClD;QACD,IAAI,EAAE,EAAE;KACX,CAAC;IAEF,IAAI,OAAO;QACP,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAE3C,OAAO,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,WAAW,CAAC,GAAW,EAAE,OAAY;IAC1C,OAAO,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC;SACrB,IAAI,CAAC,qBAAqB,CAAC;SAC3B,KAAK,CAAC,YAAY,CAAC,CAAC;AAC7B,CAAC;AAED,SAAS,qBAAqB,CAAC,QAAa;IACxC,IAAI,CAAC,QAAQ,CAAC,EAAE;QACZ,OAAO,QAAQ,CAAC,IAAI,EAAE;aACjB,IAAI,CAAC,UAAC,IAAS,IAAK,OAAA,YAAY,CAAC,IAAI,CAAC,EAAlB,CAAkB,CAAC,CAAC;IAEjD,OAAO,QAAQ,CAAC,IAAI,EAAE;SACjB,IAAI,CAAC,UAAC,IAAS,IAAK,OAAA,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,EAAnC,CAAmC,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,YAAY,CAAC,QAAa;IAC/B,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAEtB,IAAI,QAAQ,IAAI,QAAQ,CAAC,KAAK;QAC1B,yBAAe,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE/C,OAAO,OAAO,CAAC,MAAM,EAAE,CAAC;AAC5B,CAAC;AAED,kBAAe;IACX,GAAG,KAAA;IACH,IAAI,MAAA;IACJ,WAAW,aAAA;CACd,CAAC"}
 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
import ErrorDispatcher from './ErrorDispatcher';
 | 
					import ErrorDispatcher from './ErrorDispatcher';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function get(url) {
 | 
					function get(url: string) {
 | 
				
			||||||
    let options = {
 | 
					    let options = {
 | 
				
			||||||
        method: 'GET',
 | 
					        method: 'GET',
 | 
				
			||||||
        headers: {
 | 
					        headers: {
 | 
				
			||||||
@@ -12,7 +12,7 @@ function get(url) {
 | 
				
			|||||||
    return makeRequest(url, options);
 | 
					    return makeRequest(url, options);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function post(url, request) {
 | 
					function post(url: string, request: any) {
 | 
				
			||||||
    let options = {
 | 
					    let options = {
 | 
				
			||||||
        method: 'POST',
 | 
					        method: 'POST',
 | 
				
			||||||
        headers: {
 | 
					        headers: {
 | 
				
			||||||
@@ -28,22 +28,22 @@ function post(url, request) {
 | 
				
			|||||||
    return makeRequest(url, options);
 | 
					    return makeRequest(url, options);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function makeRequest(url, options) {
 | 
					function makeRequest(url: string, options: any) {
 | 
				
			||||||
    return fetch(url, options)
 | 
					    return fetch(url, options)
 | 
				
			||||||
        .then(ensureResponseSuccess)
 | 
					        .then(ensureResponseSuccess)
 | 
				
			||||||
        .catch(errorHandler);
 | 
					        .catch(errorHandler);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function ensureResponseSuccess(response) {
 | 
					function ensureResponseSuccess(response: any) {
 | 
				
			||||||
    if (!response.ok)
 | 
					    if (!response.ok)
 | 
				
			||||||
        return response.json()
 | 
					        return response.json()
 | 
				
			||||||
            .then(data => errorHandler(data));
 | 
					            .then((data: any) => errorHandler(data));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return response.text()
 | 
					    return response.text()
 | 
				
			||||||
        .then(text => text.length ? JSON.parse(text) : {});
 | 
					        .then((text: any) => text.length ? JSON.parse(text) : {});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function errorHandler(response) {
 | 
					function errorHandler(response: any) {
 | 
				
			||||||
    console.log(response);
 | 
					    console.log(response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (response && response.Error)
 | 
					    if (response && response.Error)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										59
									
								
								Birdmap/ClientApp/src/common/components/BirdmapTitle.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								Birdmap/ClientApp/src/common/components/BirdmapTitle.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
				
			|||||||
 | 
					import { Box, Typography } from '@material-ui/core';
 | 
				
			||||||
 | 
					import { BrowserRouter, NavLink, Redirect, Route, Switch } from 'react-router-dom';
 | 
				
			||||||
 | 
					import { createStyles, makeStyles, Theme } from '@material-ui/core/styles';
 | 
				
			||||||
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function BirdmapTitle(props: any) {
 | 
				
			||||||
 | 
					    const classes = useStyles();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <Box component="span" className={classes.root}>
 | 
				
			||||||
 | 
					            <Typography component="span" className={classes.bird}>
 | 
				
			||||||
 | 
					                <NavLink exact to="/" className={classes.nav_menu_item} activeClassName={classes.nav_menu_item_active}>
 | 
				
			||||||
 | 
					                    Bird
 | 
				
			||||||
 | 
					                </NavLink>
 | 
				
			||||||
 | 
					            </Typography>
 | 
				
			||||||
 | 
					            <Typography component="span" className={classes.map}>
 | 
				
			||||||
 | 
					                <NavLink exact to="/heatmap" className={classes.nav_menu_item} activeClassName={classes.nav_menu_item_active}>
 | 
				
			||||||
 | 
					                    map
 | 
				
			||||||
 | 
					                </NavLink>
 | 
				
			||||||
 | 
					            </Typography>
 | 
				
			||||||
 | 
					        </Box>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const useStyles = makeStyles((theme: Theme) =>
 | 
				
			||||||
 | 
					    createStyles({
 | 
				
			||||||
 | 
					        root: {
 | 
				
			||||||
 | 
					            display: 'inline',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        bird: {
 | 
				
			||||||
 | 
					            textAlign: "left",
 | 
				
			||||||
 | 
					            fontWeight: 1000,
 | 
				
			||||||
 | 
					            fontSize: 30,
 | 
				
			||||||
 | 
					            textShadow: '3px 3px 0px rgba(0,0,0,0.2)',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        map: {
 | 
				
			||||||
 | 
					            textAlign: "left",
 | 
				
			||||||
 | 
					            fontWeight: 100,
 | 
				
			||||||
 | 
					            fontSize: 26,
 | 
				
			||||||
 | 
					            textShadow: '2px 2px 0px rgba(0,0,0,0.2)',
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        nav_menu_item: {
 | 
				
			||||||
 | 
					            textDecoration: 'none',
 | 
				
			||||||
 | 
					            color: 'white',
 | 
				
			||||||
 | 
					            '&:hover': {
 | 
				
			||||||
 | 
					                textDecoration: 'underline',
 | 
				
			||||||
 | 
					                color: 'white',
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        nav_menu_item_active: {
 | 
				
			||||||
 | 
					            textDecoration: 'none',
 | 
				
			||||||
 | 
					            color: 'white',
 | 
				
			||||||
 | 
					            '&:hover': {
 | 
				
			||||||
 | 
					                textDecoration: 'underline',
 | 
				
			||||||
 | 
					                color: 'white',
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    }),
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
@@ -1,35 +0,0 @@
 | 
				
			|||||||
import * as React from 'react';
 | 
					 | 
				
			||||||
import { connect } from 'react-redux';
 | 
					 | 
				
			||||||
import { RouteComponentProps } from 'react-router';
 | 
					 | 
				
			||||||
import { ApplicationState } from '../store';
 | 
					 | 
				
			||||||
import * as CounterStore from '../store/Counter';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type CounterProps =
 | 
					 | 
				
			||||||
    CounterStore.CounterState &
 | 
					 | 
				
			||||||
    typeof CounterStore.actionCreators &
 | 
					 | 
				
			||||||
    RouteComponentProps<{}>;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Counter extends React.PureComponent<CounterProps> {
 | 
					 | 
				
			||||||
    public render() {
 | 
					 | 
				
			||||||
        return (
 | 
					 | 
				
			||||||
            <React.Fragment>
 | 
					 | 
				
			||||||
                <h1>Counter</h1>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                <p>This is a simple example of a React component.</p>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                <p aria-live="polite">Current count: <strong>{this.props.count}</strong></p>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                <button type="button"
 | 
					 | 
				
			||||||
                    className="btn btn-primary btn-lg"
 | 
					 | 
				
			||||||
                    onClick={() => { this.props.increment(); }}>
 | 
					 | 
				
			||||||
                    Increment
 | 
					 | 
				
			||||||
                </button>
 | 
					 | 
				
			||||||
            </React.Fragment>
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default connect(
 | 
					 | 
				
			||||||
    (state: ApplicationState) => state.counter,
 | 
					 | 
				
			||||||
    CounterStore.actionCreators
 | 
					 | 
				
			||||||
)(Counter);
 | 
					 | 
				
			||||||
@@ -1,84 +0,0 @@
 | 
				
			|||||||
import * as React from 'react';
 | 
					 | 
				
			||||||
import { connect } from 'react-redux';
 | 
					 | 
				
			||||||
import { RouteComponentProps } from 'react-router';
 | 
					 | 
				
			||||||
import { Link } from 'react-router-dom';
 | 
					 | 
				
			||||||
import { ApplicationState } from '../store';
 | 
					 | 
				
			||||||
import * as WeatherForecastsStore from '../store/WeatherForecasts';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// At runtime, Redux will merge together...
 | 
					 | 
				
			||||||
type WeatherForecastProps =
 | 
					 | 
				
			||||||
  WeatherForecastsStore.WeatherForecastsState // ... state we've requested from the Redux store
 | 
					 | 
				
			||||||
  & typeof WeatherForecastsStore.actionCreators // ... plus action creators we've requested
 | 
					 | 
				
			||||||
  & RouteComponentProps<{ startDateIndex: string }>; // ... plus incoming routing parameters
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class FetchData extends React.PureComponent<WeatherForecastProps> {
 | 
					 | 
				
			||||||
  // This method is called when the component is first added to the document
 | 
					 | 
				
			||||||
  public componentDidMount() {
 | 
					 | 
				
			||||||
    this.ensureDataFetched();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  // This method is called when the route parameters change
 | 
					 | 
				
			||||||
  public componentDidUpdate() {
 | 
					 | 
				
			||||||
    this.ensureDataFetched();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  public render() {
 | 
					 | 
				
			||||||
    return (
 | 
					 | 
				
			||||||
      <React.Fragment>
 | 
					 | 
				
			||||||
        <h1 id="tabelLabel">Weather forecast</h1>
 | 
					 | 
				
			||||||
        <p>This component demonstrates fetching data from the server and working with URL parameters.</p>
 | 
					 | 
				
			||||||
        {this.renderForecastsTable()}
 | 
					 | 
				
			||||||
        {this.renderPagination()}
 | 
					 | 
				
			||||||
      </React.Fragment>
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  private ensureDataFetched() {
 | 
					 | 
				
			||||||
    const startDateIndex = parseInt(this.props.match.params.startDateIndex, 10) || 0;
 | 
					 | 
				
			||||||
    this.props.requestWeatherForecasts(startDateIndex);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  private renderForecastsTable() {
 | 
					 | 
				
			||||||
    return (
 | 
					 | 
				
			||||||
      <table className='table table-striped' aria-labelledby="tabelLabel">
 | 
					 | 
				
			||||||
        <thead>
 | 
					 | 
				
			||||||
          <tr>
 | 
					 | 
				
			||||||
            <th>Date</th>
 | 
					 | 
				
			||||||
            <th>Temp. (C)</th>
 | 
					 | 
				
			||||||
            <th>Temp. (F)</th>
 | 
					 | 
				
			||||||
            <th>Summary</th>
 | 
					 | 
				
			||||||
          </tr>
 | 
					 | 
				
			||||||
        </thead>
 | 
					 | 
				
			||||||
        <tbody>
 | 
					 | 
				
			||||||
          {this.props.forecasts.map((forecast: WeatherForecastsStore.WeatherForecast) =>
 | 
					 | 
				
			||||||
            <tr key={forecast.date}>
 | 
					 | 
				
			||||||
              <td>{forecast.date}</td>
 | 
					 | 
				
			||||||
              <td>{forecast.temperatureC}</td>
 | 
					 | 
				
			||||||
              <td>{forecast.temperatureF}</td>
 | 
					 | 
				
			||||||
              <td>{forecast.summary}</td>
 | 
					 | 
				
			||||||
            </tr>
 | 
					 | 
				
			||||||
          )}
 | 
					 | 
				
			||||||
        </tbody>
 | 
					 | 
				
			||||||
      </table>
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  private renderPagination() {
 | 
					 | 
				
			||||||
    const prevStartDateIndex = (this.props.startDateIndex || 0) - 5;
 | 
					 | 
				
			||||||
    const nextStartDateIndex = (this.props.startDateIndex || 0) + 5;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return (
 | 
					 | 
				
			||||||
      <div className="d-flex justify-content-between">
 | 
					 | 
				
			||||||
        <Link className='btn btn-outline-secondary btn-sm' to={`/fetch-data/${prevStartDateIndex}`}>Previous</Link>
 | 
					 | 
				
			||||||
        {this.props.isLoading && <span>Loading...</span>}
 | 
					 | 
				
			||||||
        <Link className='btn btn-outline-secondary btn-sm' to={`/fetch-data/${nextStartDateIndex}`}>Next</Link>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default connect(
 | 
					 | 
				
			||||||
  (state: ApplicationState) => state.weatherForecasts, // Selects which state properties are merged into the component's props
 | 
					 | 
				
			||||||
  WeatherForecastsStore.actionCreators // Selects which action creators are merged into the component's props
 | 
					 | 
				
			||||||
)(FetchData as any);
 | 
					 | 
				
			||||||
@@ -1,23 +0,0 @@
 | 
				
			|||||||
import * as React from 'react';
 | 
					 | 
				
			||||||
import { connect } from 'react-redux';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const Home = () => (
 | 
					 | 
				
			||||||
  <div>
 | 
					 | 
				
			||||||
    <h1>Hello, world!</h1>
 | 
					 | 
				
			||||||
    <p>Welcome to your new single-page application, built with:</p>
 | 
					 | 
				
			||||||
    <ul>
 | 
					 | 
				
			||||||
      <li><a href='https://get.asp.net/'>ASP.NET Core</a> and <a href='https://msdn.microsoft.com/en-us/library/67ef8sbd.aspx'>C#</a> for cross-platform server-side code</li>
 | 
					 | 
				
			||||||
      <li><a href='https://facebook.github.io/react/'>React</a> and <a href='https://redux.js.org/'>Redux</a> for client-side code</li>
 | 
					 | 
				
			||||||
      <li><a href='http://getbootstrap.com/'>Bootstrap</a> for layout and styling</li>
 | 
					 | 
				
			||||||
    </ul>
 | 
					 | 
				
			||||||
    <p>To help you get started, we've also set up:</p>
 | 
					 | 
				
			||||||
    <ul>
 | 
					 | 
				
			||||||
      <li><strong>Client-side navigation</strong>. For example, click <em>Counter</em> then <em>Back</em> to return here.</li>
 | 
					 | 
				
			||||||
      <li><strong>Development server integration</strong>. In development mode, the development server from <code>create-react-app</code> runs in the background automatically, so your client-side resources are dynamically built on demand and the page refreshes when you modify any file.</li>
 | 
					 | 
				
			||||||
      <li><strong>Efficient production builds</strong>. In production mode, development-time features are disabled, and your <code>dotnet publish</code> configuration produces minified, efficiently bundled JavaScript files.</li>
 | 
					 | 
				
			||||||
    </ul>
 | 
					 | 
				
			||||||
    <p>The <code>ClientApp</code> subdirectory is a standard React application based on the <code>create-react-app</code> template. If you open a command prompt in that directory, you can run <code>npm</code> commands such as <code>npm test</code> or <code>npm install</code>.</p>
 | 
					 | 
				
			||||||
  </div>
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default connect()(Home);
 | 
					 | 
				
			||||||
@@ -1,12 +0,0 @@
 | 
				
			|||||||
import * as React from 'react';
 | 
					 | 
				
			||||||
import { Container } from 'reactstrap';
 | 
					 | 
				
			||||||
import NavMenu from './NavMenu';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default (props: { children?: React.ReactNode }) => (
 | 
					 | 
				
			||||||
    <React.Fragment>
 | 
					 | 
				
			||||||
        <NavMenu/>
 | 
					 | 
				
			||||||
        <Container>
 | 
					 | 
				
			||||||
            {props.children}
 | 
					 | 
				
			||||||
        </Container>
 | 
					 | 
				
			||||||
    </React.Fragment>
 | 
					 | 
				
			||||||
);
 | 
					 | 
				
			||||||
@@ -1,13 +0,0 @@
 | 
				
			|||||||
a.navbar-brand {
 | 
					 | 
				
			||||||
    white-space: normal;
 | 
					 | 
				
			||||||
    text-align: center;
 | 
					 | 
				
			||||||
    word-break: break-all;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
html { font-size: 14px; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@media (min-width: 768px) {
 | 
					 | 
				
			||||||
    html { font-size: 16px; }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.box-shadow { box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05); }
 | 
					 | 
				
			||||||
@@ -1,42 +0,0 @@
 | 
				
			|||||||
import * as React from 'react';
 | 
					 | 
				
			||||||
import { Collapse, Container, Navbar, NavbarBrand, NavbarToggler, NavItem, NavLink } from 'reactstrap';
 | 
					 | 
				
			||||||
import { Link } from 'react-router-dom';
 | 
					 | 
				
			||||||
import './NavMenu.css';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default class NavMenu extends React.PureComponent<{}, { isOpen: boolean }> {
 | 
					 | 
				
			||||||
    public state = {
 | 
					 | 
				
			||||||
        isOpen: false
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public render() {
 | 
					 | 
				
			||||||
        return (
 | 
					 | 
				
			||||||
            <header>
 | 
					 | 
				
			||||||
                <Navbar className="navbar-expand-sm navbar-toggleable-sm border-bottom box-shadow mb-3" light>
 | 
					 | 
				
			||||||
                    <Container>
 | 
					 | 
				
			||||||
                        <NavbarBrand tag={Link} to="/">Birdmap</NavbarBrand>
 | 
					 | 
				
			||||||
                        <NavbarToggler onClick={this.toggle} className="mr-2"/>
 | 
					 | 
				
			||||||
                        <Collapse className="d-sm-inline-flex flex-sm-row-reverse" isOpen={this.state.isOpen} navbar>
 | 
					 | 
				
			||||||
                            <ul className="navbar-nav flex-grow">
 | 
					 | 
				
			||||||
                                <NavItem>
 | 
					 | 
				
			||||||
                                    <NavLink tag={Link} className="text-dark" to="/">Home</NavLink>
 | 
					 | 
				
			||||||
                                </NavItem>
 | 
					 | 
				
			||||||
                                <NavItem>
 | 
					 | 
				
			||||||
                                    <NavLink tag={Link} className="text-dark" to="/counter">Counter</NavLink>
 | 
					 | 
				
			||||||
                                </NavItem>
 | 
					 | 
				
			||||||
                                <NavItem>
 | 
					 | 
				
			||||||
                                    <NavLink tag={Link} className="text-dark" to="/fetch-data">Fetch data</NavLink>
 | 
					 | 
				
			||||||
                                </NavItem>
 | 
					 | 
				
			||||||
                            </ul>
 | 
					 | 
				
			||||||
                        </Collapse>
 | 
					 | 
				
			||||||
                    </Container>
 | 
					 | 
				
			||||||
                </Navbar>
 | 
					 | 
				
			||||||
            </header>
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private toggle = () => {
 | 
					 | 
				
			||||||
        this.setState({
 | 
					 | 
				
			||||||
            isOpen: !this.state.isOpen
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,18 +1,19 @@
 | 
				
			|||||||
import React, { useState } from 'react';
 | 
					import React, { useState } from 'react';
 | 
				
			||||||
import { useHistory } from 'react-router-dom';
 | 
					import { useHistory } from 'react-router-dom';
 | 
				
			||||||
import { Box, Grid, TextField, Button, Typography, Paper } from '@material-ui/core';
 | 
					import { Box, Grid, TextField, Button, Typography, Paper, CircularProgress } from '@material-ui/core';
 | 
				
			||||||
import { makeStyles, createStyles, Theme } from '@material-ui/core/styles';
 | 
					import { makeStyles, createStyles, Theme } from '@material-ui/core/styles';
 | 
				
			||||||
import AuthService from './AuthService';
 | 
					import AuthService from './AuthService';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function MenuItem(props: any) {
 | 
					export default function Auth(props: any) {
 | 
				
			||||||
    const history = useHistory();
 | 
					    const history = useHistory();
 | 
				
			||||||
    const classes = useStyles();
 | 
					    const classes = useStyles();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const [username, setUsername] = useState(null);
 | 
					    const [username, setUsername] = useState<string>("");
 | 
				
			||||||
    const [password, setPassword] = useState(null);
 | 
					    const [password, setPassword] = useState<string>("");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const [showError, setShowError] = useState(false);
 | 
					    const [showError, setShowError] = useState(false);
 | 
				
			||||||
    const [errorMessage, setErrorMessage] = useState('');
 | 
					    const [errorMessage, setErrorMessage] = useState('');
 | 
				
			||||||
 | 
					    const [isLoggingIn, setIsLoggingIn] = useState(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const onUsernameChanged = (event: any) => {
 | 
					    const onUsernameChanged = (event: any) => {
 | 
				
			||||||
        setUsername(event.target.value);
 | 
					        setUsername(event.target.value);
 | 
				
			||||||
@@ -35,6 +36,8 @@ export default function MenuItem(props: any) {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const onLoginClicked = () => {
 | 
					    const onLoginClicked = () => {
 | 
				
			||||||
 | 
					        setIsLoggingIn(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!username) {
 | 
					        if (!username) {
 | 
				
			||||||
            setShowError(true);
 | 
					            setShowError(true);
 | 
				
			||||||
            setErrorMessage('Username required');
 | 
					            setErrorMessage('Username required');
 | 
				
			||||||
@@ -49,13 +52,15 @@ export default function MenuItem(props: any) {
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        AuthService.login(username, password).then(() => {
 | 
					        AuthService.login(username, password)
 | 
				
			||||||
 | 
					        .then(() => {
 | 
				
			||||||
            props.onAuthenticated();
 | 
					            props.onAuthenticated();
 | 
				
			||||||
            history.push('/');
 | 
					            history.push('/');
 | 
				
			||||||
 | 
					 | 
				
			||||||
        }).catch(() => {
 | 
					        }).catch(() => {
 | 
				
			||||||
            setShowError(true);
 | 
					            setShowError(true);
 | 
				
			||||||
            setErrorMessage('Invalid credentials');
 | 
					            setErrorMessage('Invalid credentials');
 | 
				
			||||||
 | 
					        }).finally(() => {
 | 
				
			||||||
 | 
					            setIsLoggingIn(false);
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -65,9 +70,15 @@ export default function MenuItem(props: any) {
 | 
				
			|||||||
            : <React.Fragment />;
 | 
					            : <React.Fragment />;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const renderLoginButton = () => {
 | 
				
			||||||
 | 
					        return isLoggingIn
 | 
				
			||||||
 | 
					            ? <CircularProgress className={classes.button} />
 | 
				
			||||||
 | 
					            : <Button className={classes.button} variant="contained" color="primary" onClick={onLoginClicked}>Sign in</Button>
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <Box className={classes.root}>
 | 
					        <Box className={classes.root}>
 | 
				
			||||||
            <Paper className={classes.paper}>
 | 
					            <Paper className={classes.paper} elevation={8}>
 | 
				
			||||||
                <Grid container className={classes.container} spacing={2}>
 | 
					                <Grid container className={classes.container} spacing={2}>
 | 
				
			||||||
                    <Grid item>
 | 
					                    <Grid item>
 | 
				
			||||||
                        <Typography component="h1" variant="h5">
 | 
					                        <Typography component="h1" variant="h5">
 | 
				
			||||||
@@ -84,7 +95,7 @@ export default function MenuItem(props: any) {
 | 
				
			|||||||
                        {renderErrorLabel()}
 | 
					                        {renderErrorLabel()}
 | 
				
			||||||
                    </Grid>
 | 
					                    </Grid>
 | 
				
			||||||
                    <Grid item xs={12} className={classes.button}>
 | 
					                    <Grid item xs={12} className={classes.button}>
 | 
				
			||||||
                        <Button className={classes.button} variant="contained" color="primary" onClick={onLoginClicked}>Login</Button>
 | 
					                        {renderLoginButton()}
 | 
				
			||||||
                    </Grid>
 | 
					                    </Grid>
 | 
				
			||||||
                </Grid>
 | 
					                </Grid>
 | 
				
			||||||
            </Paper>
 | 
					            </Paper>
 | 
				
			||||||
@@ -108,9 +119,10 @@ const useStyles = makeStyles((theme: Theme) =>
 | 
				
			|||||||
            alignItems: "center",
 | 
					            alignItems: "center",
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        paper: {
 | 
					        paper: {
 | 
				
			||||||
 | 
					            borderRadius: 15,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        button: {
 | 
					        button: {
 | 
				
			||||||
            width: '100%',
 | 
					            justifyContent: "center",
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        error: {
 | 
					        error: {
 | 
				
			||||||
            color: "red",
 | 
					            color: "red",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
"use strict";
 | 
					"use strict";
 | 
				
			||||||
Object.defineProperty(exports, "__esModule", { value: true });
 | 
					Object.defineProperty(exports, "__esModule", { value: true });
 | 
				
			||||||
var ServiceBase_1 = require("../../common/ServiceBase");
 | 
					var ServiceBase_1 = require("../../common/ServiceBase");
 | 
				
			||||||
var login_url = '/auth/authenticate';
 | 
					var login_url = 'api/auth/authenticate';
 | 
				
			||||||
exports.default = {
 | 
					exports.default = {
 | 
				
			||||||
    isAuthenticated: function () {
 | 
					    isAuthenticated: function () {
 | 
				
			||||||
        return sessionStorage.getItem('user') !== null;
 | 
					        return sessionStorage.getItem('user') !== null;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +1 @@
 | 
				
			|||||||
{"version":3,"file":"AuthService.js","sourceRoot":"","sources":["AuthService.ts"],"names":[],"mappings":";;AAAA,wDAAmD;AAEnD,IAAM,SAAS,GAAG,oBAAoB,CAAC;AAEvC,kBAAe;IACX,eAAe;QACX,OAAO,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IACnD,CAAC;IAED,KAAK,YAAC,QAAQ,EAAE,QAAQ;QACpB,IAAI,IAAI,GAAG;YACP,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,QAAQ;SACrB,CAAC;QACF,IAAI,OAAO,GAAG;YACV,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACL,cAAc,EAAE,kBAAkB;aACrC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC7B,CAAC;QAEF,OAAO,qBAAW,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC;aAC7C,IAAI,CAAC,UAAA,QAAQ;YACV,cAAc,CAAC,OAAO,CAAC,MAAM,EAAK,QAAQ,CAAC,UAAU,SAAI,QAAQ,CAAC,YAAc,CAAC,CAAC;YAClF,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;IACX,CAAC;CACJ,CAAA"}
 | 
					{"version":3,"file":"AuthService.js","sourceRoot":"","sources":["AuthService.ts"],"names":[],"mappings":";;AAAA,wDAAmD;AAEnD,IAAM,SAAS,GAAG,uBAAuB,CAAC;AAE1C,kBAAe;IACX,eAAe;QACX,OAAO,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;IACnD,CAAC;IAED,KAAK,EAAL,UAAM,QAAgB,EAAE,QAAgB;QACpC,IAAI,IAAI,GAAG;YACP,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EAAE,QAAQ;SACrB,CAAC;QACF,IAAI,OAAO,GAAG;YACV,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACL,cAAc,EAAE,kBAAkB;aACrC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC7B,CAAC;QAEF,OAAO,qBAAW,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC;aAC7C,IAAI,CAAC,UAAA,QAAQ;YACV,cAAc,CAAC,OAAO,CAAC,MAAM,EAAK,QAAQ,CAAC,UAAU,SAAI,QAAQ,CAAC,YAAc,CAAC,CAAC;YAClF,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;IACX,CAAC;CACJ,CAAA"}
 | 
				
			||||||
@@ -1,13 +1,13 @@
 | 
				
			|||||||
import ServiceBase from '../../common/ServiceBase';
 | 
					import ServiceBase from '../../common/ServiceBase';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const login_url = '/auth/authenticate';
 | 
					const login_url = 'api/auth/authenticate';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
    isAuthenticated() {
 | 
					    isAuthenticated() {
 | 
				
			||||||
        return sessionStorage.getItem('user') !== null;
 | 
					        return sessionStorage.getItem('user') !== null;
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    login(username, password) {
 | 
					    login(username: string, password: string) {
 | 
				
			||||||
        let body = {
 | 
					        let body = {
 | 
				
			||||||
            username: username,
 | 
					            username: username,
 | 
				
			||||||
            password: password
 | 
					            password: password
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,14 +0,0 @@
 | 
				
			|||||||
/* Provide sufficient contrast against white background */
 | 
					 | 
				
			||||||
a {
 | 
					 | 
				
			||||||
  color: #0366d6;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
code {
 | 
					 | 
				
			||||||
  color: #E01A76;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.btn-primary {
 | 
					 | 
				
			||||||
  color: #fff;
 | 
					 | 
				
			||||||
  background-color: #1b6ec2;
 | 
					 | 
				
			||||||
  border-color: #1861ac;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,48 +0,0 @@
 | 
				
			|||||||
import { Action, Reducer } from 'redux';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// -----------------
 | 
					 | 
				
			||||||
// STATE - This defines the type of data maintained in the Redux store.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export interface CounterState {
 | 
					 | 
				
			||||||
    count: number;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// -----------------
 | 
					 | 
				
			||||||
// ACTIONS - These are serializable (hence replayable) descriptions of state transitions.
 | 
					 | 
				
			||||||
// They do not themselves have any side-effects; they just describe something that is going to happen.
 | 
					 | 
				
			||||||
// Use @typeName and isActionType for type detection that works even after serialization/deserialization.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export interface IncrementCountAction { type: 'INCREMENT_COUNT' }
 | 
					 | 
				
			||||||
export interface DecrementCountAction { type: 'DECREMENT_COUNT' }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Declare a 'discriminated union' type. This guarantees that all references to 'type' properties contain one of the
 | 
					 | 
				
			||||||
// declared type strings (and not any other arbitrary string).
 | 
					 | 
				
			||||||
export type KnownAction = IncrementCountAction | DecrementCountAction;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------
 | 
					 | 
				
			||||||
// ACTION CREATORS - These are functions exposed to UI components that will trigger a state transition.
 | 
					 | 
				
			||||||
// They don't directly mutate state, but they can have external side-effects (such as loading data).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const actionCreators = {
 | 
					 | 
				
			||||||
    increment: () => ({ type: 'INCREMENT_COUNT' } as IncrementCountAction),
 | 
					 | 
				
			||||||
    decrement: () => ({ type: 'DECREMENT_COUNT' } as DecrementCountAction)
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------
 | 
					 | 
				
			||||||
// REDUCER - For a given state and action, returns the new state. To support time travel, this must not mutate the old state.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const reducer: Reducer<CounterState> = (state: CounterState | undefined, incomingAction: Action): CounterState => {
 | 
					 | 
				
			||||||
    if (state === undefined) {
 | 
					 | 
				
			||||||
        return { count: 0 };
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const action = incomingAction as KnownAction;
 | 
					 | 
				
			||||||
    switch (action.type) {
 | 
					 | 
				
			||||||
        case 'INCREMENT_COUNT':
 | 
					 | 
				
			||||||
            return { count: state.count + 1 };
 | 
					 | 
				
			||||||
        case 'DECREMENT_COUNT':
 | 
					 | 
				
			||||||
            return { count: state.count - 1 };
 | 
					 | 
				
			||||||
        default:
 | 
					 | 
				
			||||||
            return state;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
@@ -1,91 +0,0 @@
 | 
				
			|||||||
import { Action, Reducer } from 'redux';
 | 
					 | 
				
			||||||
import { AppThunkAction } from './';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// -----------------
 | 
					 | 
				
			||||||
// STATE - This defines the type of data maintained in the Redux store.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export interface WeatherForecastsState {
 | 
					 | 
				
			||||||
    isLoading: boolean;
 | 
					 | 
				
			||||||
    startDateIndex?: number;
 | 
					 | 
				
			||||||
    forecasts: WeatherForecast[];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export interface WeatherForecast {
 | 
					 | 
				
			||||||
    date: string;
 | 
					 | 
				
			||||||
    temperatureC: number;
 | 
					 | 
				
			||||||
    temperatureF: number;
 | 
					 | 
				
			||||||
    summary: string;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// -----------------
 | 
					 | 
				
			||||||
// ACTIONS - These are serializable (hence replayable) descriptions of state transitions.
 | 
					 | 
				
			||||||
// They do not themselves have any side-effects; they just describe something that is going to happen.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
interface RequestWeatherForecastsAction {
 | 
					 | 
				
			||||||
    type: 'REQUEST_WEATHER_FORECASTS';
 | 
					 | 
				
			||||||
    startDateIndex: number;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
interface ReceiveWeatherForecastsAction {
 | 
					 | 
				
			||||||
    type: 'RECEIVE_WEATHER_FORECASTS';
 | 
					 | 
				
			||||||
    startDateIndex: number;
 | 
					 | 
				
			||||||
    forecasts: WeatherForecast[];
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Declare a 'discriminated union' type. This guarantees that all references to 'type' properties contain one of the
 | 
					 | 
				
			||||||
// declared type strings (and not any other arbitrary string).
 | 
					 | 
				
			||||||
type KnownAction = RequestWeatherForecastsAction | ReceiveWeatherForecastsAction;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------
 | 
					 | 
				
			||||||
// ACTION CREATORS - These are functions exposed to UI components that will trigger a state transition.
 | 
					 | 
				
			||||||
// They don't directly mutate state, but they can have external side-effects (such as loading data).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const actionCreators = {
 | 
					 | 
				
			||||||
    requestWeatherForecasts: (startDateIndex: number): AppThunkAction<KnownAction> => (dispatch, getState) => {
 | 
					 | 
				
			||||||
        // Only load data if it's something we don't already have (and are not already loading)
 | 
					 | 
				
			||||||
        const appState = getState();
 | 
					 | 
				
			||||||
        if (appState && appState.weatherForecasts && startDateIndex !== appState.weatherForecasts.startDateIndex) {
 | 
					 | 
				
			||||||
            fetch(`weatherforecast`)
 | 
					 | 
				
			||||||
                .then(response => response.json() as Promise<WeatherForecast[]>)
 | 
					 | 
				
			||||||
                .then(data => {
 | 
					 | 
				
			||||||
                    dispatch({ type: 'RECEIVE_WEATHER_FORECASTS', startDateIndex: startDateIndex, forecasts: data });
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            dispatch({ type: 'REQUEST_WEATHER_FORECASTS', startDateIndex: startDateIndex });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// ----------------
 | 
					 | 
				
			||||||
// REDUCER - For a given state and action, returns the new state. To support time travel, this must not mutate the old state.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const unloadedState: WeatherForecastsState = { forecasts: [], isLoading: false };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export const reducer: Reducer<WeatherForecastsState> = (state: WeatherForecastsState | undefined, incomingAction: Action): WeatherForecastsState => {
 | 
					 | 
				
			||||||
    if (state === undefined) {
 | 
					 | 
				
			||||||
        return unloadedState;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const action = incomingAction as KnownAction;
 | 
					 | 
				
			||||||
    switch (action.type) {
 | 
					 | 
				
			||||||
        case 'REQUEST_WEATHER_FORECASTS':
 | 
					 | 
				
			||||||
            return {
 | 
					 | 
				
			||||||
                startDateIndex: action.startDateIndex,
 | 
					 | 
				
			||||||
                forecasts: state.forecasts,
 | 
					 | 
				
			||||||
                isLoading: true
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
        case 'RECEIVE_WEATHER_FORECASTS':
 | 
					 | 
				
			||||||
            // Only accept the incoming data if it matches the most recent request. This ensures we correctly
 | 
					 | 
				
			||||||
            // handle out-of-order responses.
 | 
					 | 
				
			||||||
            if (action.startDateIndex === state.startDateIndex) {
 | 
					 | 
				
			||||||
                return {
 | 
					 | 
				
			||||||
                    startDateIndex: action.startDateIndex,
 | 
					 | 
				
			||||||
                    forecasts: action.forecasts,
 | 
					 | 
				
			||||||
                    isLoading: false
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return state;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										39
									
								
								Birdmap/ClientApp/src/store/configureStore.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								Birdmap/ClientApp/src/store/configureStore.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					"use strict";
 | 
				
			||||||
 | 
					var __assign = (this && this.__assign) || function () {
 | 
				
			||||||
 | 
					    __assign = Object.assign || function(t) {
 | 
				
			||||||
 | 
					        for (var s, i = 1, n = arguments.length; i < n; i++) {
 | 
				
			||||||
 | 
					            s = arguments[i];
 | 
				
			||||||
 | 
					            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
 | 
				
			||||||
 | 
					                t[p] = s[p];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return t;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    return __assign.apply(this, arguments);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					var __spreadArrays = (this && this.__spreadArrays) || function () {
 | 
				
			||||||
 | 
					    for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
 | 
				
			||||||
 | 
					    for (var r = Array(s), k = 0, i = 0; i < il; i++)
 | 
				
			||||||
 | 
					        for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
 | 
				
			||||||
 | 
					            r[k] = a[j];
 | 
				
			||||||
 | 
					    return r;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					Object.defineProperty(exports, "__esModule", { value: true });
 | 
				
			||||||
 | 
					var redux_1 = require("redux");
 | 
				
			||||||
 | 
					var redux_thunk_1 = require("redux-thunk");
 | 
				
			||||||
 | 
					var connected_react_router_1 = require("connected-react-router");
 | 
				
			||||||
 | 
					var _1 = require("./");
 | 
				
			||||||
 | 
					function configureStore(history, initialState) {
 | 
				
			||||||
 | 
					    var middleware = [
 | 
				
			||||||
 | 
					        redux_thunk_1.default,
 | 
				
			||||||
 | 
					        connected_react_router_1.routerMiddleware(history)
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					    var rootReducer = redux_1.combineReducers(__assign(__assign({}, _1.reducers), { router: connected_react_router_1.connectRouter(history) }));
 | 
				
			||||||
 | 
					    var enhancers = [];
 | 
				
			||||||
 | 
					    var windowIfDefined = typeof window === 'undefined' ? null : window;
 | 
				
			||||||
 | 
					    if (windowIfDefined && windowIfDefined.__REDUX_DEVTOOLS_EXTENSION__) {
 | 
				
			||||||
 | 
					        enhancers.push(windowIfDefined.__REDUX_DEVTOOLS_EXTENSION__());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return redux_1.createStore(rootReducer, initialState, redux_1.compose.apply(void 0, __spreadArrays([redux_1.applyMiddleware.apply(void 0, middleware)], enhancers)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					exports.default = configureStore;
 | 
				
			||||||
 | 
					//# sourceMappingURL=configureStore.js.map
 | 
				
			||||||
							
								
								
									
										1
									
								
								Birdmap/ClientApp/src/store/configureStore.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								Birdmap/ClientApp/src/store/configureStore.js.map
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					{"version":3,"file":"configureStore.js","sourceRoot":"","sources":["configureStore.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,+BAA+E;AAC/E,2CAAgC;AAChC,iEAAyE;AAEzE,uBAAgD;AAEhD,SAAwB,cAAc,CAAC,OAAgB,EAAE,YAA+B;IACpF,IAAM,UAAU,GAAG;QACf,qBAAK;QACL,yCAAgB,CAAC,OAAO,CAAC;KAC5B,CAAC;IAEF,IAAM,WAAW,GAAG,uBAAe,uBAC5B,WAAQ,KACX,MAAM,EAAE,sCAAa,CAAC,OAAO,CAAC,IAChC,CAAC;IAEH,IAAM,SAAS,GAAG,EAAE,CAAC;IACrB,IAAM,eAAe,GAAG,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAa,CAAC;IAC7E,IAAI,eAAe,IAAI,eAAe,CAAC,4BAA4B,EAAE;QACjE,SAAS,CAAC,IAAI,CAAC,eAAe,CAAC,4BAA4B,EAAE,CAAC,CAAC;KAClE;IAED,OAAO,mBAAW,CACd,WAAW,EACX,YAAY,EACZ,eAAO,+BAAC,uBAAe,eAAI,UAAU,IAAM,SAAS,GACvD,CAAC;AACN,CAAC;AAtBD,iCAsBC"}
 | 
				
			||||||
							
								
								
									
										8
									
								
								Birdmap/ClientApp/src/store/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								Birdmap/ClientApp/src/store/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					"use strict";
 | 
				
			||||||
 | 
					Object.defineProperty(exports, "__esModule", { value: true });
 | 
				
			||||||
 | 
					exports.reducers = void 0;
 | 
				
			||||||
 | 
					// Whenever an action is dispatched, Redux will update each top-level application state property using
 | 
				
			||||||
 | 
					// the reducer with the matching name. It's important that the names match exactly, and that the reducer
 | 
				
			||||||
 | 
					// acts on the corresponding ApplicationState property type.
 | 
				
			||||||
 | 
					exports.reducers = {};
 | 
				
			||||||
 | 
					//# sourceMappingURL=index.js.map
 | 
				
			||||||
							
								
								
									
										1
									
								
								Birdmap/ClientApp/src/store/index.js.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								Birdmap/ClientApp/src/store/index.js.map
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAMA,sGAAsG;AACtG,wGAAwG;AACxG,4DAA4D;AAC/C,QAAA,QAAQ,GAAG,EACvB,CAAC"}
 | 
				
			||||||
@@ -1,18 +1,13 @@
 | 
				
			|||||||
import * as WeatherForecasts from './WeatherForecasts';
 | 
					
 | 
				
			||||||
import * as Counter from './Counter';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The top-level state object
 | 
					// The top-level state object
 | 
				
			||||||
export interface ApplicationState {
 | 
					export interface ApplicationState {
 | 
				
			||||||
    counter: Counter.CounterState | undefined;
 | 
					 | 
				
			||||||
    weatherForecasts: WeatherForecasts.WeatherForecastsState | undefined;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Whenever an action is dispatched, Redux will update each top-level application state property using
 | 
					// Whenever an action is dispatched, Redux will update each top-level application state property using
 | 
				
			||||||
// the reducer with the matching name. It's important that the names match exactly, and that the reducer
 | 
					// the reducer with the matching name. It's important that the names match exactly, and that the reducer
 | 
				
			||||||
// acts on the corresponding ApplicationState property type.
 | 
					// acts on the corresponding ApplicationState property type.
 | 
				
			||||||
export const reducers = {
 | 
					export const reducers = {
 | 
				
			||||||
    counter: Counter.reducer,
 | 
					 | 
				
			||||||
    weatherForecasts: WeatherForecasts.reducer
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This type can be used as a hint on action creators so that its 'dispatch' and 'getState' params are
 | 
					// This type can be used as a hint on action creators so that its 'dispatch' and 'getState' params are
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user