Fixed API folder name
This commit is contained in:
7
Birdmap.API/ClientApp/.eslintrc.json
Normal file
7
Birdmap.API/ClientApp/.eslintrc.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module"
|
||||
}
|
||||
}
|
21
Birdmap.API/ClientApp/.gitignore
vendored
Normal file
21
Birdmap.API/ClientApp/.gitignore
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# 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*
|
2228
Birdmap.API/ClientApp/README.md
Normal file
2228
Birdmap.API/ClientApp/README.md
Normal file
File diff suppressed because it is too large
Load Diff
14426
Birdmap.API/ClientApp/package-lock.json
generated
Normal file
14426
Birdmap.API/ClientApp/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
61
Birdmap.API/ClientApp/package.json
Normal file
61
Birdmap.API/ClientApp/package.json
Normal file
@ -0,0 +1,61 @@
|
||||
{
|
||||
"name": "birdmap",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@material-ui/core": "^4.11.0",
|
||||
"@material-ui/lab": "^4.0.0-alpha.56",
|
||||
"bootstrap": "^4.3.1",
|
||||
"connected-react-router": "6.5.2",
|
||||
"history": "4.10.1",
|
||||
"jquery": "^3.5.1",
|
||||
"merge": "1.2.1",
|
||||
"popper.js": "^1.16.0",
|
||||
"react": "16.11.0",
|
||||
"react-dom": "16.11.0",
|
||||
"react-redux": "7.1.1",
|
||||
"react-router": "5.1.2",
|
||||
"react-router-dom": "5.1.2",
|
||||
"react-scripts": "^3.4.4",
|
||||
"reactstrap": "8.1.1",
|
||||
"redux": "4.0.4",
|
||||
"redux-thunk": "2.3.0",
|
||||
"svgo": "1.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/history": "4.7.3",
|
||||
"@types/jest": "24.0.19",
|
||||
"@types/node": "12.11.6",
|
||||
"@types/react": "16.9.9",
|
||||
"@types/react-dom": "16.9.2",
|
||||
"@types/react-redux": "7.1.5",
|
||||
"@types/react-router": "5.1.2",
|
||||
"@types/react-router-dom": "5.1.0",
|
||||
"@types/reactstrap": "8.0.6",
|
||||
"@typescript-eslint/parser": "^2.5.0",
|
||||
"cross-env": "6.0.3",
|
||||
"eslint": "^6.5.1",
|
||||
"eslint-plugin-flowtype": "^3.13.0",
|
||||
"eslint-plugin-import": "2.18.2",
|
||||
"eslint-plugin-jsx-a11y": "6.2.3",
|
||||
"eslint-plugin-react": "7.16.0",
|
||||
"nan": "^2.14.1",
|
||||
"typescript": "3.6.4"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "cross-env CI=true react-scripts test --env=jsdom",
|
||||
"eject": "react-scripts eject",
|
||||
"lint": "eslint ./src/**/*.ts ./src/**/*.tsx"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
},
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not ie <= 11",
|
||||
"not op_mini all"
|
||||
]
|
||||
}
|
BIN
Birdmap.API/ClientApp/public/favicon.ico
Normal file
BIN
Birdmap.API/ClientApp/public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
41
Birdmap.API/ClientApp/public/index.html
Normal file
41
Birdmap.API/ClientApp/public/index.html
Normal file
@ -0,0 +1,41 @@
|
||||
<!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">
|
||||
<base href="%PUBLIC_URL%/" />
|
||||
<!--
|
||||
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>Birdmap</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>
|
15
Birdmap.API/ClientApp/public/manifest.json
Normal file
15
Birdmap.API/ClientApp/public/manifest.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"short_name": "Birdmap",
|
||||
"name": "Birdmap",
|
||||
"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"
|
||||
}
|
31
Birdmap.API/ClientApp/src/App.test.js
Normal file
31
Birdmap.API/ClientApp/src/App.test.js
Normal file
@ -0,0 +1,31 @@
|
||||
"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);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var React = require("react");
|
||||
var ReactDOM = require("react-dom");
|
||||
var react_redux_1 = require("react-redux");
|
||||
var react_router_dom_1 = require("react-router-dom");
|
||||
var App_1 = require("./App");
|
||||
it('renders without crashing', function () {
|
||||
var storeFake = function (state) { return ({
|
||||
default: function () { },
|
||||
subscribe: function () { },
|
||||
dispatch: function () { },
|
||||
getState: function () { return (__assign({}, state)); }
|
||||
}); };
|
||||
var store = storeFake({});
|
||||
ReactDOM.render(React.createElement(react_redux_1.Provider, { store: store },
|
||||
React.createElement(react_router_dom_1.MemoryRouter, null,
|
||||
React.createElement(App_1.default, null))), document.createElement('div'));
|
||||
});
|
||||
//# sourceMappingURL=App.test.js.map
|
1
Birdmap.API/ClientApp/src/App.test.js.map
Normal file
1
Birdmap.API/ClientApp/src/App.test.js.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"App.test.js","sourceRoot":"","sources":["App.test.tsx"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,6BAA+B;AAC/B,oCAAsC;AACtC,2CAAuC;AACvC,qDAAgD;AAChD,6BAAwB;AAExB,EAAE,CAAC,0BAA0B,EAAE;IAC3B,IAAM,SAAS,GAAG,UAAC,KAAU,IAAK,OAAA,CAAC;QAC/B,OAAO,EAAE,cAAO,CAAC;QACjB,SAAS,EAAE,cAAO,CAAC;QACnB,QAAQ,EAAE,cAAO,CAAC;QAClB,QAAQ,EAAE,cAAM,OAAA,cAAM,KAAK,EAAG,EAAd,CAAc;KACjC,CAAC,EALgC,CAKhC,CAAC;IACH,IAAM,KAAK,GAAG,SAAS,CAAC,EAAE,CAAQ,CAAC;IAEnC,QAAQ,CAAC,MAAM,CACX,oBAAC,sBAAQ,IAAC,KAAK,EAAE,KAAK;QAClB,oBAAC,+BAAY;YACT,oBAAC,aAAG,OAAE,CACK,CACR,EAAE,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;AACpD,CAAC,CAAC,CAAC"}
|
22
Birdmap.API/ClientApp/src/App.test.tsx
Normal file
22
Birdmap.API/ClientApp/src/App.test.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import App from './App';
|
||||
|
||||
it('renders without crashing', () => {
|
||||
const storeFake = (state: any) => ({
|
||||
default: () => {},
|
||||
subscribe: () => {},
|
||||
dispatch: () => {},
|
||||
getState: () => ({ ...state })
|
||||
});
|
||||
const store = storeFake({}) as any;
|
||||
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<MemoryRouter>
|
||||
<App/>
|
||||
</MemoryRouter>
|
||||
</Provider>, document.createElement('div'));
|
||||
});
|
146
Birdmap.API/ClientApp/src/App.tsx
Normal file
146
Birdmap.API/ClientApp/src/App.tsx
Normal file
@ -0,0 +1,146 @@
|
||||
import { Box, Container } from '@material-ui/core';
|
||||
import AppBar from '@material-ui/core/AppBar';
|
||||
import blue from '@material-ui/core/colors/blue';
|
||||
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 Typography from '@material-ui/core/Typography';
|
||||
import { ThemeProvider } from '@material-ui/styles';
|
||||
import React, { useState } from 'react';
|
||||
import { BrowserRouter, NavLink, Redirect, Route, Switch } from 'react-router-dom';
|
||||
import BirdmapTitle from './common/components/BirdmapTitle';
|
||||
import Auth from './components/auth/Auth';
|
||||
import AuthService from './components/auth/AuthService';
|
||||
|
||||
|
||||
const theme = createMuiTheme({
|
||||
palette: {
|
||||
primary: {
|
||||
main: blue[900],
|
||||
},
|
||||
secondary: {
|
||||
main: orange[200],
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
function App() {
|
||||
|
||||
const [authenticated, setAuthenticated] = useState(AuthService.isAuthenticated());
|
||||
|
||||
const onAuthenticated = () => {
|
||||
setAuthenticated(AuthService.isAuthenticated());
|
||||
};
|
||||
|
||||
const AuthComponent = () => {
|
||||
return (
|
||||
<Auth onAuthenticated={onAuthenticated} />
|
||||
);
|
||||
}
|
||||
|
||||
const DashboardComponent = () => {
|
||||
return <Typography>Dashboard</Typography>;
|
||||
};
|
||||
|
||||
const DevicesComponent = () => {
|
||||
return <Typography>Devices</Typography>;
|
||||
|
||||
};
|
||||
const HeatmapComponent = () => {
|
||||
return <Typography>Heatmap</Typography>;
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={theme}>
|
||||
<BrowserRouter>
|
||||
<Switch>
|
||||
<PublicRoute path="/login" component={AuthComponent} />
|
||||
<PrivateRoute path="/" exact authenticated={authenticated} component={DashboardComponent} />
|
||||
<PrivateRoute path="/devices" exact authenticated={authenticated} component={DevicesComponent} />
|
||||
<PrivateRoute path="/heatmap" exact authenticated={authenticated} component={HeatmapComponent} />
|
||||
</Switch>
|
||||
</BrowserRouter>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
||||
const PublicRoute = ({ component: Component, ...rest }: { [x: string]: any, component: any}) => {
|
||||
return (
|
||||
<Route {...rest} render={matchProps => (
|
||||
<DefaultLayout component={Component} authenticated={false} {...matchProps} />
|
||||
)} />
|
||||
);
|
||||
}
|
||||
|
||||
const PrivateRoute = ({ component: Component, authenticated: Authenticated, ...rest }: { [x: string]: any, component: any, authenticated: any }) => {
|
||||
return (
|
||||
<Route {...rest} render={matchProps => (
|
||||
Authenticated
|
||||
? <DefaultLayout component={Component} authenticated={Authenticated} {...matchProps} />
|
||||
: <Redirect to='/login' />
|
||||
)} />
|
||||
);
|
||||
};
|
||||
|
||||
const DefaultLayout = ({ component: Component, authenticated: Authenticated, ...rest }: { [x: string]: any, component: any, authenticated: any }) => {
|
||||
const classes = useDefaultLayoutStyles();
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<AppBar position="static">
|
||||
<Toolbar>
|
||||
<BirdmapTitle />
|
||||
<Typography component={'span'} className={classes.typo}>
|
||||
{renderNavLinks()}
|
||||
</Typography>
|
||||
</Toolbar>
|
||||
</AppBar>
|
||||
<Box style={{ margin: '32px' }}>
|
||||
<Component {...rest} />
|
||||
</Box>
|
||||
</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',
|
||||
}
|
||||
},
|
||||
}),
|
||||
);
|
14
Birdmap.API/ClientApp/src/common/ErrorDispatcher.js
Normal file
14
Birdmap.API/ClientApp/src/common/ErrorDispatcher.js
Normal file
@ -0,0 +1,14 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var ErrorDispatcher = {
|
||||
errorHandlers: [],
|
||||
registerErrorHandler: function (errorHandlerFn) {
|
||||
this.errorHandlers.push(errorHandlerFn);
|
||||
},
|
||||
raiseError: function (errorMessage) {
|
||||
for (var i = 0; i < this.errorHandlers.length; i++)
|
||||
this.errorHandlers[i](errorMessage);
|
||||
}
|
||||
};
|
||||
exports.default = ErrorDispatcher;
|
||||
//# sourceMappingURL=ErrorDispatcher.js.map
|
1
Birdmap.API/ClientApp/src/common/ErrorDispatcher.js.map
Normal file
1
Birdmap.API/ClientApp/src/common/ErrorDispatcher.js.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"ErrorDispatcher.js","sourceRoot":"","sources":["ErrorDispatcher.ts"],"names":[],"mappings":";;AAAA,IAAM,eAAe,GAAG;IACtB,aAAa,EAAE,EAAE;IAEjB,oBAAoB,YAAC,cAAc;QACjC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAC1C,CAAC;IAED,UAAU,YAAC,YAAY;QACrB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE;YAChD,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACxC,CAAC;CACF,CAAC;AAEF,kBAAe,eAAe,CAAC"}
|
14
Birdmap.API/ClientApp/src/common/ErrorDispatcher.ts
Normal file
14
Birdmap.API/ClientApp/src/common/ErrorDispatcher.ts
Normal file
@ -0,0 +1,14 @@
|
||||
const ErrorDispatcher = {
|
||||
errorHandlers: [],
|
||||
|
||||
registerErrorHandler(errorHandlerFn) {
|
||||
this.errorHandlers.push(errorHandlerFn);
|
||||
},
|
||||
|
||||
raiseError(errorMessage) {
|
||||
for (let i = 0; i < this.errorHandlers.length; i++)
|
||||
this.errorHandlers[i](errorMessage);
|
||||
}
|
||||
};
|
||||
|
||||
export default ErrorDispatcher;
|
50
Birdmap.API/ClientApp/src/common/ServiceBase.js
Normal file
50
Birdmap.API/ClientApp/src/common/ServiceBase.js
Normal file
@ -0,0 +1,50 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var ErrorDispatcher_1 = require("./ErrorDispatcher");
|
||||
function get(url) {
|
||||
var options = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
return makeRequest(url, options);
|
||||
}
|
||||
function post(url, request) {
|
||||
var options = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
},
|
||||
body: "",
|
||||
};
|
||||
if (request)
|
||||
options.body = JSON.stringify(request);
|
||||
return makeRequest(url, options);
|
||||
}
|
||||
function makeRequest(url, options) {
|
||||
return fetch(url, options)
|
||||
.then(ensureResponseSuccess)
|
||||
.catch(errorHandler);
|
||||
}
|
||||
function ensureResponseSuccess(response) {
|
||||
if (!response.ok)
|
||||
return response.json()
|
||||
.then(function (data) { return errorHandler(data); });
|
||||
return response.text()
|
||||
.then(function (text) { return text.length ? JSON.parse(text) : {}; });
|
||||
}
|
||||
function errorHandler(response) {
|
||||
console.log(response);
|
||||
if (response && response.Error)
|
||||
ErrorDispatcher_1.default.raiseError(response.Error);
|
||||
return Promise.reject();
|
||||
}
|
||||
exports.default = {
|
||||
get: get,
|
||||
post: post,
|
||||
makeRequest: makeRequest
|
||||
};
|
||||
//# sourceMappingURL=ServiceBase.js.map
|
1
Birdmap.API/ClientApp/src/common/ServiceBase.js.map
Normal file
1
Birdmap.API/ClientApp/src/common/ServiceBase.js.map
Normal file
@ -0,0 +1 @@
|
||||
{"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"}
|
59
Birdmap.API/ClientApp/src/common/ServiceBase.ts
Normal file
59
Birdmap.API/ClientApp/src/common/ServiceBase.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import ErrorDispatcher from './ErrorDispatcher';
|
||||
|
||||
function get(url: string) {
|
||||
let options = {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
}
|
||||
};
|
||||
|
||||
return makeRequest(url, options);
|
||||
}
|
||||
|
||||
function post(url: string, request: any) {
|
||||
let options = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': sessionStorage.getItem('user')
|
||||
},
|
||||
body: "",
|
||||
};
|
||||
|
||||
if (request)
|
||||
options.body = JSON.stringify(request);
|
||||
|
||||
return makeRequest(url, options);
|
||||
}
|
||||
|
||||
function makeRequest(url: string, options: any) {
|
||||
return fetch(url, options)
|
||||
.then(ensureResponseSuccess)
|
||||
.catch(errorHandler);
|
||||
}
|
||||
|
||||
function ensureResponseSuccess(response: any) {
|
||||
if (!response.ok)
|
||||
return response.json()
|
||||
.then((data: any) => errorHandler(data));
|
||||
|
||||
return response.text()
|
||||
.then((text: any) => text.length ? JSON.parse(text) : {});
|
||||
}
|
||||
|
||||
function errorHandler(response: any) {
|
||||
console.log(response);
|
||||
|
||||
if (response && response.Error)
|
||||
ErrorDispatcher.raiseError(response.Error);
|
||||
|
||||
return Promise.reject();
|
||||
}
|
||||
|
||||
export default {
|
||||
get,
|
||||
post,
|
||||
makeRequest
|
||||
};
|
59
Birdmap.API/ClientApp/src/common/components/BirdmapTitle.tsx
Normal file
59
Birdmap.API/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',
|
||||
}
|
||||
},
|
||||
}),
|
||||
);
|
131
Birdmap.API/ClientApp/src/components/auth/Auth.tsx
Normal file
131
Birdmap.API/ClientApp/src/components/auth/Auth.tsx
Normal file
@ -0,0 +1,131 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { Box, Grid, TextField, Button, Typography, Paper, CircularProgress } from '@material-ui/core';
|
||||
import { makeStyles, createStyles, Theme } from '@material-ui/core/styles';
|
||||
import AuthService from './AuthService';
|
||||
|
||||
export default function Auth(props: any) {
|
||||
const history = useHistory();
|
||||
const classes = useStyles();
|
||||
|
||||
const [username, setUsername] = useState<string>("");
|
||||
const [password, setPassword] = useState<string>("");
|
||||
|
||||
const [showError, setShowError] = useState(false);
|
||||
const [errorMessage, setErrorMessage] = useState('');
|
||||
const [isLoggingIn, setIsLoggingIn] = useState(false);
|
||||
|
||||
const onUsernameChanged = (event: any) => {
|
||||
setUsername(event.target.value);
|
||||
|
||||
setShowError(false);
|
||||
setErrorMessage('');
|
||||
};
|
||||
|
||||
const onPasswordChanged = (event: any) => {
|
||||
setPassword(event.target.value);
|
||||
|
||||
setShowError(false);
|
||||
setErrorMessage('');
|
||||
};
|
||||
|
||||
const onPasswordKeyPress = (event: any) => {
|
||||
if (event.key === 'Enter') {
|
||||
onLoginClicked();
|
||||
}
|
||||
};
|
||||
|
||||
const onLoginClicked = () => {
|
||||
setIsLoggingIn(true);
|
||||
|
||||
if (!username) {
|
||||
setShowError(true);
|
||||
setErrorMessage('Username required');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!password) {
|
||||
setShowError(true);
|
||||
setErrorMessage('Password required');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
AuthService.login(username, password)
|
||||
.then(() => {
|
||||
props.onAuthenticated();
|
||||
history.push('/');
|
||||
}).catch(() => {
|
||||
setShowError(true);
|
||||
setErrorMessage('Invalid credentials');
|
||||
}).finally(() => {
|
||||
setIsLoggingIn(false);
|
||||
});
|
||||
};
|
||||
|
||||
const renderErrorLabel = () => {
|
||||
return showError
|
||||
? <Typography>{errorMessage}</Typography>
|
||||
: <React.Fragment />;
|
||||
};
|
||||
|
||||
const renderLoginButton = () => {
|
||||
return isLoggingIn
|
||||
? <CircularProgress className={classes.button} />
|
||||
: <Button className={classes.button} variant="contained" color="primary" onClick={onLoginClicked}>Sign in</Button>
|
||||
};
|
||||
|
||||
return (
|
||||
<Box className={classes.root}>
|
||||
<Paper className={classes.paper} elevation={8}>
|
||||
<Grid container className={classes.container} spacing={2}>
|
||||
<Grid item>
|
||||
<Typography component="h1" variant="h5">
|
||||
Sign in
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid item xs={12} >
|
||||
<TextField label="Username" type="text" onChange={onUsernameChanged} />
|
||||
</Grid>
|
||||
<Grid item xs={12} >
|
||||
<TextField label="Password" type="password" onChange={onPasswordChanged} onKeyPress={onPasswordKeyPress} />
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.error}>
|
||||
{renderErrorLabel()}
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.button}>
|
||||
{renderLoginButton()}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Paper>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
root: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
minWidth: 400,
|
||||
minHeight: 600,
|
||||
},
|
||||
container: {
|
||||
padding: 40,
|
||||
flexDirection: "column",
|
||||
justifyContent: "space-around",
|
||||
alignItems: "center",
|
||||
},
|
||||
paper: {
|
||||
borderRadius: 15,
|
||||
},
|
||||
button: {
|
||||
justifyContent: "center",
|
||||
},
|
||||
error: {
|
||||
color: "red",
|
||||
}
|
||||
}),
|
||||
);
|
28
Birdmap.API/ClientApp/src/components/auth/AuthService.js
Normal file
28
Birdmap.API/ClientApp/src/components/auth/AuthService.js
Normal file
@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
var ServiceBase_1 = require("../../common/ServiceBase");
|
||||
var login_url = 'api/auth/authenticate';
|
||||
exports.default = {
|
||||
isAuthenticated: function () {
|
||||
return sessionStorage.getItem('user') !== null;
|
||||
},
|
||||
login: function (username, password) {
|
||||
var body = {
|
||||
username: username,
|
||||
password: password
|
||||
};
|
||||
var options = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
};
|
||||
return ServiceBase_1.default.makeRequest(login_url, options)
|
||||
.then(function (response) {
|
||||
sessionStorage.setItem('user', response.token_type + " " + response.access_token);
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=AuthService.js.map
|
@ -0,0 +1 @@
|
||||
{"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"}
|
29
Birdmap.API/ClientApp/src/components/auth/AuthService.ts
Normal file
29
Birdmap.API/ClientApp/src/components/auth/AuthService.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import ServiceBase from '../../common/ServiceBase';
|
||||
|
||||
const login_url = 'api/auth/authenticate';
|
||||
|
||||
export default {
|
||||
isAuthenticated() {
|
||||
return sessionStorage.getItem('user') !== null;
|
||||
},
|
||||
|
||||
login(username: string, password: string) {
|
||||
let body = {
|
||||
username: username,
|
||||
password: password
|
||||
};
|
||||
let options = {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(body),
|
||||
};
|
||||
|
||||
return ServiceBase.makeRequest(login_url, options)
|
||||
.then(response => {
|
||||
sessionStorage.setItem('user', `${response.token_type} ${response.access_token}`);
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
}
|
21
Birdmap.API/ClientApp/src/index.js
Normal file
21
Birdmap.API/ClientApp/src/index.js
Normal file
@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
require("bootstrap/dist/css/bootstrap.css");
|
||||
var React = require("react");
|
||||
var ReactDOM = require("react-dom");
|
||||
var react_redux_1 = require("react-redux");
|
||||
var connected_react_router_1 = require("connected-react-router");
|
||||
var history_1 = require("history");
|
||||
var configureStore_1 = require("./store/configureStore");
|
||||
var App_1 = require("./App");
|
||||
var registerServiceWorker_1 = require("./registerServiceWorker");
|
||||
// Create browser history to use in the Redux store
|
||||
var baseUrl = document.getElementsByTagName('base')[0].getAttribute('href');
|
||||
var history = history_1.createBrowserHistory({ basename: baseUrl });
|
||||
// Get the application-wide store instance, prepopulating with state from the server where available.
|
||||
var store = configureStore_1.default(history);
|
||||
ReactDOM.render(React.createElement(react_redux_1.Provider, { store: store },
|
||||
React.createElement(connected_react_router_1.ConnectedRouter, { history: history },
|
||||
React.createElement(App_1.default, null))), document.getElementById('root'));
|
||||
registerServiceWorker_1.default();
|
||||
//# sourceMappingURL=index.js.map
|
1
Birdmap.API/ClientApp/src/index.js.map
Normal file
1
Birdmap.API/ClientApp/src/index.js.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.tsx"],"names":[],"mappings":";;AAAA,4CAA0C;AAE1C,6BAA+B;AAC/B,oCAAsC;AACtC,2CAAuC;AACvC,iEAAyD;AACzD,mCAA+C;AAC/C,yDAAoD;AACpD,6BAAwB;AACxB,iEAA4D;AAE5D,mDAAmD;AACnD,IAAM,OAAO,GAAG,QAAQ,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAW,CAAC;AACxF,IAAM,OAAO,GAAG,8BAAoB,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;AAE5D,qGAAqG;AACrG,IAAM,KAAK,GAAG,wBAAc,CAAC,OAAO,CAAC,CAAC;AAEtC,QAAQ,CAAC,MAAM,CACX,oBAAC,sBAAQ,IAAC,KAAK,EAAE,KAAK;IAClB,oBAAC,wCAAe,IAAC,OAAO,EAAE,OAAO;QAC7B,oBAAC,aAAG,OAAG,CACO,CACX,EACX,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;AAErC,+BAAqB,EAAE,CAAC"}
|
27
Birdmap.API/ClientApp/src/index.tsx
Normal file
27
Birdmap.API/ClientApp/src/index.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import 'bootstrap/dist/css/bootstrap.css';
|
||||
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
import { ConnectedRouter } from 'connected-react-router';
|
||||
import { createBrowserHistory } from 'history';
|
||||
import configureStore from './store/configureStore';
|
||||
import App from './App';
|
||||
import registerServiceWorker from './registerServiceWorker';
|
||||
|
||||
// Create browser history to use in the Redux store
|
||||
const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href') as string;
|
||||
const history = createBrowserHistory({ basename: baseUrl });
|
||||
|
||||
// Get the application-wide store instance, prepopulating with state from the server where available.
|
||||
const store = configureStore(history);
|
||||
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
<ConnectedRouter history={history}>
|
||||
<App />
|
||||
</ConnectedRouter>
|
||||
</Provider>,
|
||||
document.getElementById('root'));
|
||||
|
||||
registerServiceWorker();
|
1
Birdmap.API/ClientApp/src/react-app-env.d.ts
vendored
Normal file
1
Birdmap.API/ClientApp/src/react-app-env.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
/// <reference types="react-scripts" />
|
105
Birdmap.API/ClientApp/src/registerServiceWorker.ts
Normal file
105
Birdmap.API/ClientApp/src/registerServiceWorker.ts
Normal file
@ -0,0 +1,105 @@
|
||||
// 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 url = process.env.PUBLIC_URL as string;
|
||||
const publicUrl = new URL(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);
|
||||
} 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 as ServiceWorker;
|
||||
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.
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (response.status === 404 || (contentType && contentType.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();
|
||||
});
|
||||
}
|
||||
}
|
39
Birdmap.API/ClientApp/src/store/configureStore.js
Normal file
39
Birdmap.API/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.API/ClientApp/src/store/configureStore.js.map
Normal file
1
Birdmap.API/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"}
|
29
Birdmap.API/ClientApp/src/store/configureStore.ts
Normal file
29
Birdmap.API/ClientApp/src/store/configureStore.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import { applyMiddleware, combineReducers, compose, createStore } from 'redux';
|
||||
import thunk from 'redux-thunk';
|
||||
import { connectRouter, routerMiddleware } from 'connected-react-router';
|
||||
import { History } from 'history';
|
||||
import { ApplicationState, reducers } from './';
|
||||
|
||||
export default function configureStore(history: History, initialState?: ApplicationState) {
|
||||
const middleware = [
|
||||
thunk,
|
||||
routerMiddleware(history)
|
||||
];
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
...reducers,
|
||||
router: connectRouter(history)
|
||||
});
|
||||
|
||||
const enhancers = [];
|
||||
const windowIfDefined = typeof window === 'undefined' ? null : window as any;
|
||||
if (windowIfDefined && windowIfDefined.__REDUX_DEVTOOLS_EXTENSION__) {
|
||||
enhancers.push(windowIfDefined.__REDUX_DEVTOOLS_EXTENSION__());
|
||||
}
|
||||
|
||||
return createStore(
|
||||
rootReducer,
|
||||
initialState,
|
||||
compose(applyMiddleware(...middleware), ...enhancers)
|
||||
);
|
||||
}
|
8
Birdmap.API/ClientApp/src/store/index.js
Normal file
8
Birdmap.API/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.API/ClientApp/src/store/index.js.map
Normal file
1
Birdmap.API/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"}
|
17
Birdmap.API/ClientApp/src/store/index.ts
Normal file
17
Birdmap.API/ClientApp/src/store/index.ts
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
|
||||
// The top-level state object
|
||||
export interface ApplicationState {
|
||||
}
|
||||
|
||||
// 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.
|
||||
export const reducers = {
|
||||
};
|
||||
|
||||
// This type can be used as a hint on action creators so that its 'dispatch' and 'getState' params are
|
||||
// correctly typed to match your store.
|
||||
export interface AppThunkAction<TAction> {
|
||||
(dispatch: (action: TAction) => void, getState: () => ApplicationState): void;
|
||||
}
|
24
Birdmap.API/ClientApp/tsconfig.json
Normal file
24
Birdmap.API/ClientApp/tsconfig.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"allowJs": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "preserve",
|
||||
"lib": [
|
||||
"es2015",
|
||||
"dom"
|
||||
],
|
||||
"skipLibCheck": false
|
||||
},
|
||||
"include": [
|
||||
"src"
|
||||
]
|
||||
}
|
Reference in New Issue
Block a user