Have main and listSystems working

This commit is contained in:
Luke Berndt
2021-01-01 12:04:37 -05:00
parent ac6b9903a6
commit 79fe8113e0
24 changed files with 881 additions and 246 deletions

8
frontend/.env Normal file
View File

@@ -0,0 +1,8 @@
REACT_APP_BACKEND_SERVER=https://api.openmhz.com
REACT_APP_FRONTEND_SERVER=https://openmhz.com
REACT_APP_SOCKET_SERVER=wss://api.openmhz.com
REACT_APP_SITE_NAME=OpenMHz
REACT_APP_PRO_PLAN=1
REACT_APP_FREE_PLAN=0
REACT_APP_PRO_PLAN_ARCHIVE=30
REACT_APP_FREE_PLAN_ARCHIVE=7

File diff suppressed because one or more lines are too long

8
frontend/env-example Normal file
View File

@@ -0,0 +1,8 @@
REACT_APP_BACKEND_SERVER=https://api.openmhz.com
REACT_APP_FRONTEND_SERVER=https://openmhz.com
REACT_APP_SOCKET_SERVER=wss://api.openmhz.com
REACT_APP_SITE_NAME=OpenMHz
REACT_APP_PRO_PLAN=1
REACT_APP_FREE_PLAN=0
REACT_APP_PRO_PLAN_ARCHIVE=30
REACT_APP_FREE_PLAN_ARCHIVE=7

View File

@@ -0,0 +1,12 @@
## Elements Used
- Create React App
- Redux
- Redux Router
- [Redux Thunk](https://github.com/reduxjs/redux-thunk): lets you do AJAX calls
- [connected-react-router](https://github.com/supasate/connected-react-router): Synchronize router state with redux store through uni-directional flow (i.e. history -> store -> router -> components). Basically, if you go back the redux store will update... I think
- [axios](https://github.com/axios/axios) - library for doing HTTP requests
- [@artsy/fresnel](https://github.com/artsy/fresnel) - Handles media requests for responsive designs and works server side too. https://github.com/Semantic-Org/Semantic-UI-React/pull/4008
## Environment Variables
CRA lets you sub in env variables into both HTML and JS: https://create-react-app.dev/docs/adding-custom-environment-variables/

View File

@@ -3,19 +3,21 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@artsy/fresnel": "1.3.1",
"@reduxjs/toolkit": "^1.1.0",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"bootstrap": "4.5.3",
"axios": "0.21.1",
"connected-react-router": "6.8.0",
"react": "^17.0.1",
"react-bootstrap": "1.4.0",
"react-dom": "^17.0.1",
"react-redux": "^7.1.3",
"react-router-dom": "5.2.0",
"react-scripts": "4.0.1",
"redux-thunk": "2.3.0"
"redux-thunk": "2.3.0",
"semantic-ui-css": "2.4.1",
"semantic-ui-react": "2.0.1"
},
"scripts": {
"start": "react-scripts start",

View File

@@ -24,6 +24,10 @@
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`.
-->
<script src="%REACT_APP_BACKEND_SERVER%/socket.io/socket.io.js"></script>
<script>
const socket = io('%REACT_APP_BACKEND_SERVER%');
</script>
<title>React Redux App</title>
</head>
<body>

View File

@@ -1,39 +0,0 @@
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-float infinite 3s ease-in-out;
}
}
.App-header {
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
}
.App-link {
color: rgb(112, 76, 182);
}
@keyframes App-logo-float {
0% {
transform: translateY(0);
}
50% {
transform: translateY(10px)
}
100% {
transform: translateY(0px)
}
}

View File

@@ -1,58 +0,0 @@
import React from 'react';
import logo from './logo.svg';
import { Counter } from './features/counter/Counter';
import './App.css';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<Counter />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<span>
<span>Learn </span>
<a
className="App-link"
href="https://reactjs.org/"
target="_blank"
rel="noopener noreferrer"
>
React
</a>
<span>, </span>
<a
className="App-link"
href="https://redux.js.org/"
target="_blank"
rel="noopener noreferrer"
>
Redux
</a>
<span>, </span>
<a
className="App-link"
href="https://redux-toolkit.js.org/"
target="_blank"
rel="noopener noreferrer"
>
Redux Toolkit
</a>
,<span> and </span>
<a
className="App-link"
href="https://react-redux.js.org/"
target="_blank"
rel="noopener noreferrer"
>
React Redux
</a>
</span>
</header>
</div>
);
}
export default App;

View File

@@ -1,15 +0,0 @@
import React from 'react';
import { render } from '@testing-library/react';
import { Provider } from 'react-redux';
import store from './app/store';
import App from './App';
test('renders learn react link', () => {
const { getByText } = render(
<Provider store={store}>
<App />
</Provider>
);
expect(getByText(/learn/i)).toBeInTheDocument();
});

View File

@@ -0,0 +1,82 @@
@font-face {
font-family: didact;
src: url("../resources/DidactGothic-Regular.ttf");
}
#menu-bar {
background-color: #365474;
}
.header {
font-family: didact !important;
}
#header-bg {
position: relative;
}
#hero {
height: 725px;
}
.z-0 {
z-index: 0;
}
.z-5 {
z-index: 5;
}
.absolute {
position: absolute;
}
.relative {
position: relative;
}
.static-gradient-bg {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB8AAAAfBAMAAADtgAsKAAAAD1BMVEUAAAAAAAAAAAAAAAAAAABPDueNAAAABXRSTlMVGRsSHUz7Vs0AAAErSURBVCjPHY+BDeUgDEPttAM4wACk/QMEdYHSu/1nOjghQIodPxnRfuPnfWQO0F240K5TvRLKdYXvdAIH8ej+0yTEsh1CUYplr+j91ouhCl3WhEnpNuACvW3vUAgic8woHoA/ojO5MN6uN9EPdIJpRu7IBfTN5+I4aIAowPxSu74OAV7gfFuLJVQeAKS41Kes5k4H6tW8uML0yJcjHTE3WepIAfx+8JhJ6aCeRMRK7EQs9RjPxhheOhZL+P//zh8TW4gKArKGY2m3H1xZgq0ykzzdh9vrWPu4c1eNc0bs+suKQAKmtg4gT4kqleFxCzT1zftKUzmYi0CqWynyr4YSwhq2q/s8pf9l+oD9nbeZAXRAlJ0wFMd43ICcpTanOIQXEDTjdK54eqlV+Q9M1SO8F3P79wAAAABJRU5ErkJggg==");
width: 100%;
height: 100%;
}
/*
.static-gradient.blue {
background: -webkit-gradient(linear,left top,right top,from(#2754F0),to(#86ACFE));
background: linear-gradient(to right, #2754F0, #86ACFE);
}*/
.static-gradient.blue {
background: -webkit-gradient(linear,left top,right top,from(#9f0000),to(#ff7543));
background: linear-gradient(to right, #9f0000, #ff7543);
}
.static-gradient {
width: 100%;
height: 100%;
overflow: hidden;
-webkit-transform: skewY(-7deg);
transform: skewY(-7deg);
-webkit-transform-origin: 0;
transform-origin: 0;
border-bottom: 2px solid rgba(128,128,128,.5);
bottom: 0;
}
#menu-bg {
background-color: #3b5f85;
}
#footer {
background: -webkit-gradient(linear, bottom, top,from(#9f0000),to(#ff7543));
background: linear-gradient(to top, #9f0000, #ff7543);
}
.ui.button {
}

356
frontend/src/Main/Main.js Normal file
View File

@@ -0,0 +1,356 @@
import React, { Component } from "react";
import { Link } from 'react-router-dom'
import SystemCard from "../System/SystemCard";
import "./Main.css";
import { createMedia } from "@artsy/fresnel";
import {
Button,
Container,
Divider,
Grid,
Header,
Icon,
Menu,
Segment,
Sidebar,
Transition,
} from 'semantic-ui-react'
/* Responsive component was removed from Semantic UI. This is discussed here: https://github.com/Semantic-Org/Semantic-UI-React/pull/4008 */
const AppMedia = createMedia({
breakpoints: {
mobile: 320,
tablet: 768,
computer: 992,
largeScreen: 1200,
widescreen: 1920
}
});
const mediaStyles = AppMedia.createMediaStyle();
const { Media } = AppMedia;
/* eslint-disable react/no-multi-comp */
/* Heads up! HomepageHeading uses inline styling, however it's not the best practice. Use CSS or styled components for
* such things.
*/
const HomepageHeading = ({ mobile }) => (
<Container text style={{paddingBottom: '0px'}} >
<Header
as='h1'
content='Share the Air'
style={{
fontSize: mobile ? '2em' : '4em',
color: "#FFF",
fontWeight: 'normal',
marginBottom: 0,
marginTop: mobile ? '1.5em' : '0em',
}}
/>
<Header
as='h2'
content='Listen to Police and Fire radio from across the US'
style={{
fontSize: mobile ? '1.5em' : '1.7em',
color: "#FFF",
fontWeight: 'normal',
marginTop: mobile ? '0.5em' : '1.5em',
marginBottom: mobile ? '0.5em' : '0em',
}}
/>
</Container>
)
/*
HomepageHeading.propTypes = {
mobile: PropTypes.bool,
}
*/
/* Heads up!
* Neither Semantic UI nor Semantic UI React offer a responsive navbar, however, it can be implemented easily.
* It can be more complicated, but you can create really flexible markup.
*/
/*
General flow:
- componentDidMount(): it will call fetchSystem() this will perform an HTTP request if Systems does not exist, and then add System to Props
*/
class DesktopContainer extends Component {
state = {}
hideFixedMenu = () => this.setState({ fixed: false })
showFixedMenu = () => this.setState({ fixed: true })
render() {
const { children } = this.props
const { fixed } = this.state
return (
<Media greaterThanOrEqual="tablet">
<div className="relative">
<div className="static-gradient blue absolute z-0" >
<div className="static-gradient-bg absolute z-5"></div>
</div>
<Segment
textAlign='center'
style={{ padding: '1em 0em',
borderBottom: '0px',
boxShadow: 'none',
height: '400px'
}}
vertical
>
<Menu
fixed={fixed ? 'top' : null}
inverted={true}
pointing={false}
secondary={true}
size='huge'
style={{ marginRight: '0px'}}
>
<Container>
<Menu.Item ><Header as='h3' inverted>{process.env.REACT_APP_SITE_NAME}</Header></Menu.Item>
<Link to="/systems"><Menu.Item link >Listen</Menu.Item></Link>
<Link to="/about"><Menu.Item link >About</Menu.Item></Link>
</Container>
</Menu>
<HomepageHeading />
</Segment>
</div>
{children}
</Media>
)
}
}
/*
DesktopContainer.propTypes = {
children: PropTypes.node,
}
*/
class MobileContainer extends Component {
state = {}
handlePusherClick = () => {
const { sidebarOpened } = this.state
if (sidebarOpened) this.setState({ sidebarOpened: false })
}
handleToggle = () => this.setState({ sidebarOpened: !this.state.sidebarOpened })
render() {
const { children } = this.props
const { sidebarOpened } = this.state
return (
<Media lessThan="tablet">
<Sidebar.Pushable>
<Sidebar as={Menu} animation='uncover' inverted vertical visible={sidebarOpened} id="menu-bar">
<Menu.Item active>
Home
</Menu.Item>
<Menu.Item ><Link to="/systems">Systems</Link></Menu.Item>
<Menu.Item ><Link to="/about">About</Link></Menu.Item>
</Sidebar>
<Sidebar.Pusher
dimmed={sidebarOpened}
onClick={this.handlePusherClick}
style={{ minHeight: '100vh' }}
>
<div className='relative'>
<div className="static-gradient blue absolute z-0">
<div className="static-gradient-bg absolute"></div>
</div>
<Segment
textAlign='center'
style={{ minHeight: 350, padding: '1em 0em',
borderBottom: '0px',
boxShadow: 'none',
height: '300px'}}
vertical
>
<Container>
<Menu inverted secondary size='large'>
<Menu.Item onClick={this.handleToggle}>
<Icon name='sidebar' />
</Menu.Item>
<Menu.Item header>{process.env.REACT_APP_SITE_NAME}</Menu.Item>
</Menu>
</Container>
<HomepageHeading mobile />
</Segment>
</div>
{children}
</Sidebar.Pusher>
</Sidebar.Pushable>
</Media>
)
}
}
/*
MobileContainer.propTypes = {
children: PropTypes.node,
}
*/
const ResponsiveContainer = ({ children }) => (
<div>
<DesktopContainer>{children}</DesktopContainer>
<MobileContainer>{children}</MobileContainer>
</div>
)
// ----------------------------------------------------
class Main extends Component {
constructor(props) {
super(props);
this.advanceSystem = this.advanceSystem.bind(this);
this.state = { duration: 500, visible: true, currentSystem: 0}
}
handleChange = (e, { name, value }) => this.setState({ [name]: value })
handleVisibility = () => this.setState({ visible: !this.state.visible })
advanceSystem() {
var currentSystem = this.state.currentSystem + 1;
if (currentSystem > this.props.system.items.length) {
currentSystem = 0;
}
this.setState({ visible: !this.state.visible, currentSystem });
}
componentDidMount() {
this.props.fetchSystems();
this.interval = setInterval(() => this.advanceSystem(), 3000);
}
componentWillUnmount() {
clearInterval(this.interval);
}
//https://stackoverflow.com/questions/36559661/how-can-i-dispatch-from-child-components-in-react-redux
//https://stackoverflow.com/questions/42597602/react-onclick-pass-event-with-parameter
render() {
const system = this.props.system.items[this.state.currentSystem];
return (
<>
<style>{mediaStyles}</style>
<ResponsiveContainer>
<div style={{ top: '-120px', position: 'relative' }}>
<Segment style={{ padding: ' 0em', height: '350px', backgroudColor: '#FFF'}} vertical>
<Grid columns='equal' stackable textAlign='center' style={{ height: '350px', marginRight: '0px' }}>
<Grid.Row textAlign='center'>
<Grid.Column style={{ paddingBottom: '4em', paddingTop: '2em', maxWidth: 450 }}>
{ system && (<Transition visible={this.state.visible} animation='pulse' duration={500}>
<SystemCard keepShort={true} system={system} key={system.shortName} onClick={(e) => this.props.changeUrl("/system/" + system.shortName)}/>
</Transition>)}
</Grid.Column>
<Grid.Column style={{ paddingBottom: '0em', paddingTop: '6em', maxWidth: 450 }}>
<Link to="/systems">
<Button primary size='huge' id="listen" animated>
<Button.Content visible><Icon name='headphones' />
<Icon name='right arrow' /></Button.Content>
<Button.Content hidden>Listen</Button.Content>
</Button>
</Link>
</Grid.Column>
</Grid.Row>
</Grid>
</Segment>
<Segment style={{ padding: '0em' }} vertical>
<Grid celled='internally' columns='equal' stackable>
<Grid.Row textAlign='center'>
<Grid.Column style={{ paddingBottom: '5em', paddingTop: '5em' }}>
<Header as='h3' style={{ fontSize: '2em' }}>
<Icon color='orange' name='list' />All The Calls
</Header>
<p style={{ fontSize: '1.33em' }}>Every call, on every talkgroup is recorded</p>
</Grid.Column>
<Grid.Column style={{ paddingBottom: '5em', paddingTop: '5em' }}>
<Header as='h3' style={{ fontSize: '2em' }}>
<Icon color='orange' name='checked calendar' />
Go back in time
</Header>
<p style={{ fontSize: '1.33em' }}>
Missed a call? Not a problem, everything is archived!
</p>
</Grid.Column>
</Grid.Row>
</Grid>
</Segment>
<Segment style={{ padding: '8em 0em' }} vertical>
<Container text>
<Header as='h3' style={{ fontSize: '2em' }}>
Don't just scan, hear it all!
</Header>
<p style={{ fontSize: '1.33em' }}>
Most large cities use trunked radio systems to get the most use out of their assigned radio spectrum. With trunked systems, the transmission are constantly hopping to different frequencies. Using a cheap Software Defined Radio (SDR), it is possible capture all of the transmission on a system.
Instead of scanning to a single frequency, SDR capturea wide swathes of spectrum, covering all of the frequencies a system could use.
</p>
<Divider
as='h4'
className='header'
horizontal
style={{ margin: '3em 0em', textTransform: 'uppercase' }}
>
Get Involved
</Divider>
<Header as='h3' style={{ fontSize: '2em' }}>
Want to record your local radio system?
</Header>
<p style={{ fontSize: '1.33em' }}>
Join us! Record a local radio system and share it with the world. If you have a spare computer, it is easy to get started. With a $25 SDR or two, you can capture an entire system.
It does take a little bit of work to get things setup, but we are here to help and answer questions.
</p>
<a href="https://github.com/robotastic/trunk-recorder/blob/master/README.md">
<Button size='large'>
Learn More
</Button>
</a>
</Container>
</Segment>
</div>
<Segment inverted vertical style={{ padding: '5em 0em' }} id="footer">
<Container>
<Grid divided inverted stackable>
<Grid.Row>
<Grid.Column width={6}>
</Grid.Column>
<Grid.Column width={4}>
<Header as='h4' inverted>
The End <Icon name='rocket' />
</Header>
</Grid.Column>
<Grid.Column width={6}>
</Grid.Column>
</Grid.Row>
</Grid>
</Container>
</Segment>
</ResponsiveContainer>
</>);
}
}
export default Main;

View File

@@ -0,0 +1,16 @@
import { connect } from "react-redux"
import * as systemActions from "../System/system-actions"
import Main from "./Main"
function mapStateToProps(state) {
return {
system: state.system
}
}
export default connect(
mapStateToProps,
systemActions
)(Main)

View File

@@ -0,0 +1,49 @@
import React, { Component } from "react";
import { Link } from 'react-router-dom'
import SystemCard from "./SystemCard";
import {
Container,
Header,
Card,
Icon,
Menu,
Divider
} from "semantic-ui-react";
// ----------------------------------------------------
class ListSystems extends Component {
state = {
requestMessage: "",
}
componentDidMount() {
this.props.fetchSystems();
}
//https://stackoverflow.com/questions/36559661/how-can-i-dispatch-from-child-components-in-react-redux
//https://stackoverflow.com/questions/42597602/react-onclick-pass-event-with-parameter
render() {
const systems = this.props.system.items;
return (
<div>
<Menu fixed="top">
<Link to="/"><Menu.Item link><Icon name='arrow left' /> Home</Menu.Item></Link>
<Link to="/about"><Menu.Item link>About</Menu.Item></Link>
</Menu>
<Container >
<Divider horizontal style={{paddingTop:"5em", paddingBottom:"2em"}}><Header as="h1">Radio Systems<Icon name='rss' /></Header></Divider>
<Card.Group itemsPerRow={4} stackable={true}>
{systems.map((system) =>
system.active&&<SystemCard system={system} key={system.shortName} onClick={(e) => this.props.changeUrl("/system/" + system.shortName)}/>
// <SystemCard system={system} key={system.shortName} onClick={(e) => this.props.changeUrl("/system/" + system.shortName)}/>
)}
</Card.Group>
</Container>
</div>
);
}
}
export default ListSystems;

View File

@@ -0,0 +1,16 @@
import { connect } from "react-redux"
import * as systemActions from "./system-actions"
import ListSystems from "./ListSystems"
function mapStateToProps(state) {
return {
system: state.system
}
}
export default connect(
mapStateToProps,
systemActions
)(ListSystems)

View File

@@ -0,0 +1,71 @@
import React, { Component } from "react";
import {
Card,
Icon,
Label,
Grid
} from "semantic-ui-react";
class SystemCard extends Component {
render() {
var location = "";
const system = this.props.system;
var clientCount = "";
var callAvg = "";
var description = system.description;
if (this.props.keepShort && (description.length > 100)) {
description = description.substring(0, 96) + "...";
}
if (system.callAvg) {
callAvg = Math.round(system.callAvg * 10) / 10 + " call/min"
}
if (system.clientCount === 1) {
clientCount = "1 listener";
} else if (system.clientCount > 1) {
clientCount = system.clientCount + " listeners"
}
if (system) {
switch (system.systemType) {
case "state":
location = system.state;
break;
case "city":
location = system.city + ", " + system.state;
break;
case "county":
location = system.county + ", " + system.state;
break;
case "international":
location = system.country;
break;
default:
location = system.city + ", " + system.state;
}
}
return (
<Card link onClick={this.props.onClick} raised={true} centered={true} >
<Card.Content>
<Card.Header >{system.name}</Card.Header>
<Card.Meta>{system.screenName && <Label size="mini"><Icon name='user' /> {system.screenName}</Label>}</Card.Meta>
</Card.Content>
<Card.Content description={description} />
<Card.Content extra>
<Icon name='marker' />
{location}
<Grid columns={2}>
<Grid.Column>
{clientCount && <div><Icon name='headphones' />{clientCount}</div>}
</Grid.Column>
<Grid.Column>
{callAvg && <div><Icon name='file audio outline' />{callAvg}</div>}
</Grid.Column>
</Grid>
</Card.Content>
</Card>
);
}
}
export default SystemCard;

View File

@@ -0,0 +1,77 @@
import axios from "axios";
//import { browserHistory } from "react-router"
import * as types from "./system-constants";
import { push } from 'connected-react-router';
const FETCH_SUCCESS_STATISTIC = "FETCH_SUCCESS_STATISTIC"
function beginFetchSystem() {
return { type: types.FETCH_SYSTEM };
}
function fetchSystemSuccess(data) {
return { type: types.FETCH_SUCCESS_SYSTEM,
data };
}
function fetchSystemError(data) {
return { type: types.FETCH_ERROR_SYSTEM,
data };
}
function makeUserRequest(method, data, api = "/login") {
// returns a Promise
return axios({
method: method,
url: api,
data: data
});
}
export function changeUrl(url) {
return dispatch => {
dispatch(push(url));
};
}
// Example of an Async Action Creator
// http://redux.js.org/docs/advanced/AsyncActions.html
function shouldFetchSystems(state, subreddit) {
if ((!state.system.items) || (state.system.items.length <1)) {
return true
} else if (state.system.isWaiting) {
return false
} else {
return false
}
}
export function fetchSystems() {
return (dispatch, getState) => {
if (shouldFetchSystems(getState())) {
dispatch(beginFetchSystem());
return axios
.get(process.env.REACT_APP_BACKEND_SERVER + "/systems")
.then(response => {
if (response.data.success) {
dispatch(fetchSystemSuccess(response.data.systems));
} else {
dispatch(fetchSystemError());
let registerMessage = response.data.message;
return registerMessage;
}
})
.catch(response => {
if (response instanceof Error) {
// Something happened in setting up the request that triggered an Error
console.log("Error", response.message);
}
});
};
};
}

View File

@@ -0,0 +1,3 @@
export const FETCH_SYSTEM = "FETCH_SYSTEM"
export const FETCH_SUCCESS_SYSTEM = "FETCH_SUCCESS_SYSTEM"
export const FETCH_ERROR_SYSTEM = "FETCH_ERROR_SYSTEM"

View File

@@ -0,0 +1,71 @@
import {
CREATE_SYSTEM,
CREATE_SUCCESS_SYSTEM,
CREATE_ERROR_SYSTEM,
UPDATE_SYSTEM,
UPDATE_SUCCESS_SYSTEM,
UPDATE_ERROR_SYSTEM,
DELETE_SYSTEM,
DELETE_SUCCESS_SYSTEM,
DELETE_ERROR_SYSTEM,
FETCH_SYSTEM,
FETCH_SUCCESS_SYSTEM,
FETCH_ERROR_SYSTEM
} from "./system-constants";
function updateObject(oldObject, newValues) {
// Encapsulate the idea of passing a new object as the first parameter
// to Object.assign to ensure we correctly copy data instead of mutating
return Object.assign({}, oldObject, newValues);
}
function updateObjectInArray(array, shortName, updatedItem) {
return array.map( item => {
if(item.shortName !== shortName) {
// This isn't the item we care about - keep it as-is
return item;
}
// Otherwise, this is the one we want - return an updated value
return {
...item,
...updatedItem
};
});
}
const system = (
state = {
isWaiting: false,
items: []},
action
) => {
switch (action.type) {
case FETCH_SYSTEM:
return Object.assign({}, state, { isWaiting: true});
case FETCH_SUCCESS_SYSTEM:
const activeSystems = action.data.filter(system =>{
if (system.active) {return true}
return false;
});
return Object.assign({}, state, {
isWaiting: false,
items: activeSystems
});
case FETCH_ERROR_SYSTEM:
return Object.assign({}, state, {
isWaiting: false
});
default:
return state;
}
};
export default system;

View File

@@ -3,10 +3,14 @@ import ReactDOM from 'react-dom';
import { Provider } from 'react-redux'
import { Route, Switch } from 'react-router' // react-router v4/v5
import { ConnectedRouter } from 'connected-react-router'
import configureStore, { history } from './app/configureStore'
import configureStore, { history } from './redux-router/configureStore'
import 'semantic-ui-css/semantic.min.css'
import App from './App';
// Main
import MainContainer from "./Main/MainContainer"
// System
import ListSystemsContainer from "./System/ListSystemsContainer"
const store = configureStore(/* provide initial state if any */)
@@ -15,7 +19,8 @@ ReactDOM.render(
<ConnectedRouter history={history}> { /* place ConnectedRouter under Provider */ }
<> { /* your usual react-router v4/v5 routing */ }
<Switch>
<Route exact path="/" render={() => (<App />)} />
<Route exact path="/" component={MainContainer} />
<Route exact path="/systems" component={ListSystemsContainer} />
<Route render={() => (<div>Miss</div>)} />
</Switch>
</>

View File

@@ -2,11 +2,11 @@
// from https://github.com/supasate/connected-react-router
import { combineReducers } from 'redux'
import { connectRouter } from 'connected-react-router'
import counterReducer from '../features/counter/counterSlice';
import systemReducer from "../System/system-reducer"
const createRootReducer = (history) => combineReducers({
router: connectRouter(history),
counter: counterReducer,
system: systemReducer,
})
export default createRootReducer

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -2,6 +2,10 @@
# yarn lockfile v1
"@artsy/fresnel@1.3.1":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@artsy/fresnel/-/fresnel-1.3.1.tgz#1df2ea9bb7b6a1a4e7ae9aa837f2af1a402ee3cf"
"@babel/code-frame@7.10.4", "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.5.5":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a"
@@ -968,7 +972,7 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.4.2", "@babel/runtime@^7.5.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.5.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4":
version "7.12.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.5.tgz#410e7e487441e1b360c29be715d870d9b985882e"
dependencies:
@@ -1038,6 +1042,19 @@
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
"@fluentui/react-component-event-listener@~0.51.1":
version "0.51.4"
resolved "https://registry.yarnpkg.com/@fluentui/react-component-event-listener/-/react-component-event-listener-0.51.4.tgz#4d3173a947a827973ba522ef7e1d2303694d0157"
dependencies:
"@babel/runtime" "^7.10.4"
"@fluentui/react-component-ref@~0.51.1":
version "0.51.4"
resolved "https://registry.yarnpkg.com/@fluentui/react-component-ref/-/react-component-ref-0.51.4.tgz#d538ae42642ee267c180e0a2c95ea417c1fbcbeb"
dependencies:
"@babel/runtime" "^7.10.4"
react-is "^16.6.3"
"@hapi/address@2.x.x":
version "2.1.4"
resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5"
@@ -1291,7 +1308,7 @@
schema-utils "^2.6.5"
source-map "^0.7.3"
"@popperjs/core@^2.5.3":
"@popperjs/core@^2.5.2":
version "2.6.0"
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.6.0.tgz#f022195afdfc942e088ee2101285a1d31c7d727f"
@@ -1304,17 +1321,6 @@
redux-thunk "^2.3.0"
reselect "^4.0.0"
"@restart/context@^2.1.4":
version "2.1.4"
resolved "https://registry.yarnpkg.com/@restart/context/-/context-2.1.4.tgz#a99d87c299a34c28bd85bb489cb07bfd23149c02"
"@restart/hooks@^0.3.21", "@restart/hooks@^0.3.25":
version "0.3.25"
resolved "https://registry.yarnpkg.com/@restart/hooks/-/hooks-0.3.25.tgz#11004139ad1c70d2f5965a8939dcb5aeb96aa652"
dependencies:
lodash "^4.17.15"
lodash-es "^4.17.15"
"@rollup/plugin-node-resolve@^7.1.1":
version "7.1.3"
resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz#80de384edfbd7bfc9101164910f86078151a3eca"
@@ -1340,6 +1346,13 @@
estree-walker "^1.0.1"
picomatch "^2.2.2"
"@semantic-ui-react/event-stack@^3.1.0":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@semantic-ui-react/event-stack/-/event-stack-3.1.1.tgz#3263d17511db81a743167fe45281a24b3eb6b3c8"
dependencies:
exenv "^1.2.2"
prop-types "^15.6.2"
"@sheerun/mutationobserver-shim@^0.3.2":
version "0.3.3"
resolved "https://registry.yarnpkg.com/@sheerun/mutationobserver-shim/-/mutationobserver-shim-0.3.3.tgz#5405ee8e444ed212db44e79351f0c70a582aae25"
@@ -1540,10 +1553,6 @@
dependencies:
"@babel/types" "^7.3.0"
"@types/classnames@^2.2.10":
version "2.2.11"
resolved "https://registry.yarnpkg.com/@types/classnames/-/classnames-2.2.11.tgz#2521cc86f69d15c5b90664e4829d84566052c1cf"
"@types/eslint@^7.2.4":
version "7.2.5"
resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.2.5.tgz#92172ecf490c2fce4b076739693d75f30376d610"
@@ -1576,10 +1585,6 @@
version "5.1.1"
resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#3c9ee980f1a10d6021ae6632ca3e79ca2ec4fb50"
"@types/invariant@^2.2.33":
version "2.2.34"
resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.34.tgz#05e4f79f465c2007884374d4795452f995720bbe"
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762"
@@ -1631,7 +1636,7 @@
version "2.1.5"
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.1.5.tgz#b6ab3bba29e16b821d84e09ecfaded462b816b00"
"@types/prop-types@*", "@types/prop-types@^15.7.3":
"@types/prop-types@*":
version "15.7.3"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
@@ -1645,12 +1650,6 @@
dependencies:
"@types/react" "*"
"@types/react-transition-group@^4.4.0":
version "4.4.0"
resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.0.tgz#882839db465df1320e4753e6e9f70ca7e9b4d46d"
dependencies:
"@types/react" "*"
"@types/react@*":
version "17.0.0"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.0.tgz#5af3eb7fad2807092f0046a1302b7823e27919b8"
@@ -1658,13 +1657,6 @@
"@types/prop-types" "*"
csstype "^3.0.2"
"@types/react@^16.9.11", "@types/react@^16.9.35":
version "16.14.2"
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.14.2.tgz#85dcc0947d0645349923c04ccef6018a1ab7538c"
dependencies:
"@types/prop-types" "*"
csstype "^3.0.2"
"@types/resolve@0.0.8":
version "0.0.8"
resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194"
@@ -1709,10 +1701,6 @@
dependencies:
source-map "^0.6.1"
"@types/warning@^3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.0.tgz#0d2501268ad8f9962b740d387c4654f5f8e23e52"
"@types/webpack-sources@*":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-2.0.0.tgz#08216ab9be2be2e1499beaebc4d469cec81e82a7"
@@ -2288,6 +2276,12 @@ axe-core@^4.0.2:
version "4.1.1"
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.1.1.tgz#70a7855888e287f7add66002211a423937063eaf"
axios@0.21.1:
version "0.21.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8"
dependencies:
follow-redirects "^1.10.0"
axobject-query@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
@@ -2538,10 +2532,6 @@ boolbase@^1.0.0, boolbase@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
bootstrap@4.5.3:
version "4.5.3"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.5.3.tgz#c6a72b355aaf323920be800246a6e4ef30997fe6"
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -2919,10 +2909,6 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
classnames@^2.2.6:
version "2.2.6"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
clean-css@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78"
@@ -2957,6 +2943,10 @@ clone-deep@^4.0.1:
kind-of "^6.0.2"
shallow-clone "^3.0.0"
clsx@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188"
co@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
@@ -3702,13 +3692,6 @@ dom-converter@^0.2:
dependencies:
utila "~0.4"
dom-helpers@^5.0.1, dom-helpers@^5.1.2, dom-helpers@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.0.tgz#57fd054c5f8f34c52a3eeffdb7e7e93cd357d95b"
dependencies:
"@babel/runtime" "^7.8.7"
csstype "^3.0.2"
dom-serializer@0:
version "0.2.2"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51"
@@ -4256,6 +4239,10 @@ execa@^4.0.0:
signal-exit "^3.0.2"
strip-final-newline "^2.0.0"
exenv@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d"
exit@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
@@ -4523,6 +4510,10 @@ follow-redirects@^1.0.0:
version "1.13.0"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db"
follow-redirects@^1.10.0:
version "1.13.1"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.1.tgz#5f69b813376cee4fd0474a3aba835df04ab763b7"
for-in@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
@@ -5167,12 +5158,6 @@ internal-slot@^1.0.2:
has "^1.0.3"
side-channel "^1.0.2"
invariant@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
dependencies:
loose-envify "^1.0.0"
ip-regex@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9"
@@ -5941,6 +5926,10 @@ jest@26.6.0:
import-local "^3.0.2"
jest-cli "^26.6.0"
jquery@x.*:
version "3.5.1"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.5.1.tgz#d7b4d08e1bfdb86ad2f1a3d039ea17304717abb5"
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
@@ -6065,6 +6054,10 @@ jsprim@^1.2.2:
array-includes "^3.1.1"
object.assign "^4.1.1"
keyboard-key@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/keyboard-key/-/keyboard-key-1.1.0.tgz#6f2e8e37fa11475bb1f1d65d5174f1b35653f5b7"
killable@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892"
@@ -7836,13 +7829,6 @@ prompts@2.4.0, prompts@^2.0.1:
kleur "^3.0.3"
sisteransi "^1.0.5"
prop-types-extra@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/prop-types-extra/-/prop-types-extra-1.1.1.tgz#58c3b74cbfbb95d304625975aa2f0848329a010b"
dependencies:
react-is "^16.3.2"
warning "^4.0.0"
prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
@@ -7985,29 +7971,6 @@ react-app-polyfill@^2.0.0:
regenerator-runtime "^0.13.7"
whatwg-fetch "^3.4.1"
react-bootstrap@1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/react-bootstrap/-/react-bootstrap-1.4.0.tgz#806a8b48b065cedfb28c6c5c7b0c0e3c3b53445d"
dependencies:
"@babel/runtime" "^7.4.2"
"@restart/context" "^2.1.4"
"@restart/hooks" "^0.3.21"
"@types/classnames" "^2.2.10"
"@types/invariant" "^2.2.33"
"@types/prop-types" "^15.7.3"
"@types/react" "^16.9.35"
"@types/react-transition-group" "^4.4.0"
"@types/warning" "^3.0.0"
classnames "^2.2.6"
dom-helpers "^5.1.2"
invariant "^2.2.4"
prop-types "^15.7.2"
prop-types-extra "^1.1.0"
react-overlays "^4.1.0"
react-transition-group "^4.4.1"
uncontrollable "^7.0.0"
warning "^4.0.3"
react-dev-utils@^11.0.1:
version "11.0.1"
resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-11.0.1.tgz#30106c2055acfd6b047d2dc478a85c356e66fe45"
@@ -8049,7 +8012,11 @@ react-error-overlay@^6.0.8:
version "6.0.8"
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.8.tgz#474ed11d04fc6bda3af643447d85e9127ed6b5de"
react-is@^16.12.0, react-is@^16.13.1, react-is@^16.3.2, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4:
react-fast-compare@^3.0.1:
version "3.2.0"
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb"
react-is@^16.12.0, react-is@^16.13.1, react-is@^16.6.0, react-is@^16.6.3, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
@@ -8057,22 +8024,12 @@ react-is@^17.0.1:
version "17.0.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.1.tgz#5b3531bd76a645a4c9fb6e693ed36419e3301339"
react-lifecycles-compat@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
react-overlays@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-4.1.1.tgz#0060107cbe1c5171a744ccda3fbf0556d064bc5f"
react-popper@^2.2.3:
version "2.2.4"
resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-2.2.4.tgz#d2ad3d2474ac9f1abf93df3099d408e5aa6a2e22"
dependencies:
"@babel/runtime" "^7.12.1"
"@popperjs/core" "^2.5.3"
"@restart/hooks" "^0.3.25"
"@types/warning" "^3.0.0"
dom-helpers "^5.2.0"
prop-types "^15.7.2"
uncontrollable "^7.0.0"
warning "^4.0.3"
react-fast-compare "^3.0.1"
warning "^4.0.2"
react-redux@^7.1.3:
version "7.2.2"
@@ -8180,15 +8137,6 @@ react-scripts@4.0.1:
optionalDependencies:
fsevents "^2.1.3"
react-transition-group@^4.4.1:
version "4.4.1"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9"
dependencies:
"@babel/runtime" "^7.5.5"
dom-helpers "^5.0.1"
loose-envify "^1.4.0"
prop-types "^15.6.2"
react@^17.0.1:
version "17.0.1"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.1.tgz#6e0600416bd57574e3f86d92edba3d9008726127"
@@ -8693,6 +8641,30 @@ selfsigned@^1.10.7:
dependencies:
node-forge "^0.10.0"
semantic-ui-css@2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/semantic-ui-css/-/semantic-ui-css-2.4.1.tgz#f5aea39fafb787cbd905ec724272a3f9cba9004a"
dependencies:
jquery x.*
semantic-ui-react@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/semantic-ui-react/-/semantic-ui-react-2.0.1.tgz#a69aa65001c437ae0b3ed747d1f43ee5b4e88407"
dependencies:
"@babel/runtime" "^7.10.5"
"@fluentui/react-component-event-listener" "~0.51.1"
"@fluentui/react-component-ref" "~0.51.1"
"@popperjs/core" "^2.5.2"
"@semantic-ui-react/event-stack" "^3.1.0"
clsx "^1.1.1"
keyboard-key "^1.1.0"
lodash "^4.17.19"
lodash-es "^4.17.15"
prop-types "^15.7.2"
react-is "^16.8.6"
react-popper "^2.2.3"
shallowequal "^1.1.0"
"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0:
version "5.7.1"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
@@ -8798,6 +8770,10 @@ shallow-clone@^3.0.0:
dependencies:
kind-of "^6.0.2"
shallowequal@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@@ -9581,15 +9557,6 @@ typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
uncontrollable@^7.0.0:
version "7.1.1"
resolved "https://registry.yarnpkg.com/uncontrollable/-/uncontrollable-7.1.1.tgz#f67fed3ef93637126571809746323a9db815d556"
dependencies:
"@babel/runtime" "^7.6.3"
"@types/react" "^16.9.11"
invariant "^2.2.4"
react-lifecycles-compat "^3.0.4"
unicode-canonical-property-names-ecmascript@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818"
@@ -9828,7 +9795,7 @@ walker@^1.0.7, walker@~1.0.5:
dependencies:
makeerror "1.0.x"
warning@^4.0.0, warning@^4.0.3:
warning@^4.0.2:
version "4.0.3"
resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
dependencies: