mirror of
https://github.com/openmhz/trunk-server.git
synced 2026-11-11 00:07:30 -05:00
Have main and listSystems working
This commit is contained in:
8
frontend/.env
Normal file
8
frontend/.env
Normal 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
8
frontend/env-example
Normal 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
|
||||
@@ -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/
|
||||
@@ -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",
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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();
|
||||
});
|
||||
82
frontend/src/Main/Main.css
Normal file
82
frontend/src/Main/Main.css
Normal 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
356
frontend/src/Main/Main.js
Normal 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;
|
||||
16
frontend/src/Main/MainContainer.js
Normal file
16
frontend/src/Main/MainContainer.js
Normal 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)
|
||||
49
frontend/src/System/ListSystems.js
Normal file
49
frontend/src/System/ListSystems.js
Normal 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;
|
||||
16
frontend/src/System/ListSystemsContainer.js
Normal file
16
frontend/src/System/ListSystemsContainer.js
Normal 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)
|
||||
71
frontend/src/System/SystemCard.js
Normal file
71
frontend/src/System/SystemCard.js
Normal 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;
|
||||
77
frontend/src/System/system-actions.js
Normal file
77
frontend/src/System/system-actions.js
Normal 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);
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
}
|
||||
3
frontend/src/System/system-constants.js
Normal file
3
frontend/src/System/system-constants.js
Normal 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"
|
||||
71
frontend/src/System/system-reducer.js
Normal file
71
frontend/src/System/system-reducer.js
Normal 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;
|
||||
@@ -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>
|
||||
</>
|
||||
|
||||
@@ -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
|
||||
|
||||
BIN
frontend/src/resources/DidactGothic-Regular.ttf
Executable file
BIN
frontend/src/resources/DidactGothic-Regular.ttf
Executable file
Binary file not shown.
BIN
frontend/src/resources/logo.png
Normal file
BIN
frontend/src/resources/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user