diff --git a/frontend/.env b/frontend/.env new file mode 100644 index 0000000..f536405 --- /dev/null +++ b/frontend/.env @@ -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 diff --git a/frontend/.eslintcache b/frontend/.eslintcache index d0571d3..e7a807f 100644 --- a/frontend/.eslintcache +++ b/frontend/.eslintcache @@ -1 +1 @@ -[{"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/index.js":"1","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/features/counter/Counter.js":"2","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/App.js":"3","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/app/reducers.js":"4","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/features/counter/counterSlice.js":"5","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/app/configureStore.js":"6"},{"size":824,"mtime":1609425644251,"results":"7","hashOfConfig":"8"},{"size":1626,"mtime":499162500000,"results":"9","hashOfConfig":"8"},{"size":1463,"mtime":499162500000,"results":"10","hashOfConfig":"8"},{"size":375,"mtime":1609425733654,"results":"11","hashOfConfig":"8"},{"size":1551,"mtime":499162500000,"results":"12","hashOfConfig":"8"},{"size":759,"mtime":1609425817988,"results":"13","hashOfConfig":"8"},{"filePath":"14","messages":"15","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1du4mf8",{"filePath":"16","messages":"17","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"18","messages":"19","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"20","messages":"21","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"22","messages":"23","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"24","messages":"25","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/index.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/features/counter/Counter.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/App.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/app/reducers.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/features/counter/counterSlice.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/app/configureStore.js",[]] \ No newline at end of file +[{"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/index.js":"1","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/features/counter/Counter.js":"2","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/features/counter/counterSlice.js":"3","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/SystemCard.js":"4","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/system-actions.js":"5","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/system-constants.js":"6","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Main/Main.js":"7","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/system-reducer.js":"8","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/ListSystems.js":"9","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/redux-router/reducers.js":"10"},{"size":910,"mtime":1609515100233,"results":"11","hashOfConfig":"12"},{"size":1626,"mtime":499162500000,"results":"13","hashOfConfig":"12"},{"size":1551,"mtime":499162500000,"results":"14","hashOfConfig":"12"},{"size":2045,"mtime":1609520570000,"results":"15","hashOfConfig":"12"},{"size":1789,"mtime":1609517296613,"results":"16","hashOfConfig":"12"},{"size":157,"mtime":1545362103913,"results":"17","hashOfConfig":"12"},{"size":11040,"mtime":1609520223847,"results":"18","hashOfConfig":"12"},{"size":1576,"mtime":1609520031487,"results":"19","hashOfConfig":"12"},{"size":1547,"mtime":1609520315634,"results":"20","hashOfConfig":"12"},{"size":363,"mtime":1609510513079,"results":"21","hashOfConfig":"12"},{"filePath":"22","messages":"23","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1du4mf8",{"filePath":"24","messages":"25","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"26","messages":"27","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"28","messages":"29","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"30","messages":"31","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"32","messages":"33","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"34","messages":"35","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"36","messages":"37","errorCount":0,"warningCount":11,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"38","messages":"39","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"40","messages":"41","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/index.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/features/counter/Counter.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/features/counter/counterSlice.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/SystemCard.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/system-actions.js",["42","43"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/system-constants.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Main/Main.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/system-reducer.js",["44","45","46","47","48","49","50","51","52","53","54"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/ListSystems.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/redux-router/reducers.js",[],{"ruleId":"55","severity":1,"message":"56","line":6,"column":7,"nodeType":"57","messageId":"58","endLine":6,"endColumn":30},{"ruleId":"55","severity":1,"message":"59","line":23,"column":10,"nodeType":"57","messageId":"58","endLine":23,"endColumn":25},{"ruleId":"55","severity":1,"message":"60","line":2,"column":3,"nodeType":"57","messageId":"58","endLine":2,"endColumn":16},{"ruleId":"55","severity":1,"message":"61","line":3,"column":3,"nodeType":"57","messageId":"58","endLine":3,"endColumn":24},{"ruleId":"55","severity":1,"message":"62","line":4,"column":3,"nodeType":"57","messageId":"58","endLine":4,"endColumn":22},{"ruleId":"55","severity":1,"message":"63","line":5,"column":3,"nodeType":"57","messageId":"58","endLine":5,"endColumn":16},{"ruleId":"55","severity":1,"message":"64","line":6,"column":3,"nodeType":"57","messageId":"58","endLine":6,"endColumn":24},{"ruleId":"55","severity":1,"message":"65","line":7,"column":3,"nodeType":"57","messageId":"58","endLine":7,"endColumn":22},{"ruleId":"55","severity":1,"message":"66","line":8,"column":3,"nodeType":"57","messageId":"58","endLine":8,"endColumn":16},{"ruleId":"55","severity":1,"message":"67","line":9,"column":3,"nodeType":"57","messageId":"58","endLine":9,"endColumn":24},{"ruleId":"55","severity":1,"message":"68","line":10,"column":3,"nodeType":"57","messageId":"58","endLine":10,"endColumn":22},{"ruleId":"55","severity":1,"message":"69","line":16,"column":10,"nodeType":"57","messageId":"58","endLine":16,"endColumn":22},{"ruleId":"55","severity":1,"message":"70","line":22,"column":10,"nodeType":"57","messageId":"58","endLine":22,"endColumn":29},"no-unused-vars","'FETCH_SUCCESS_STATISTIC' is assigned a value but never used.","Identifier","unusedVar","'makeUserRequest' is defined but never used.","'CREATE_SYSTEM' is defined but never used.","'CREATE_SUCCESS_SYSTEM' is defined but never used.","'CREATE_ERROR_SYSTEM' is defined but never used.","'UPDATE_SYSTEM' is defined but never used.","'UPDATE_SUCCESS_SYSTEM' is defined but never used.","'UPDATE_ERROR_SYSTEM' is defined but never used.","'DELETE_SYSTEM' is defined but never used.","'DELETE_SUCCESS_SYSTEM' is defined but never used.","'DELETE_ERROR_SYSTEM' is defined but never used.","'updateObject' is defined but never used.","'updateObjectInArray' is defined but never used."] \ No newline at end of file diff --git a/frontend/env-example b/frontend/env-example new file mode 100644 index 0000000..f536405 --- /dev/null +++ b/frontend/env-example @@ -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 diff --git a/frontend/notes.md b/frontend/notes.md index e69de29..1ed2345 100644 --- a/frontend/notes.md +++ b/frontend/notes.md @@ -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/ \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index d794de8..7075e46 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -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", diff --git a/frontend/public/index.html b/frontend/public/index.html index 430b58f..cf3a044 100644 --- a/frontend/public/index.html +++ b/frontend/public/index.html @@ -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`. --> + + React Redux App diff --git a/frontend/src/App.css b/frontend/src/App.css deleted file mode 100644 index 355c49b..0000000 --- a/frontend/src/App.css +++ /dev/null @@ -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) - } -} diff --git a/frontend/src/App.js b/frontend/src/App.js deleted file mode 100644 index 7825dd2..0000000 --- a/frontend/src/App.js +++ /dev/null @@ -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 ( -
-
- logo - -

- Edit src/App.js and save to reload. -

- - Learn - - React - - , - - Redux - - , - - Redux Toolkit - - , and - - React Redux - - -
-
- ); -} - -export default App; diff --git a/frontend/src/App.test.js b/frontend/src/App.test.js deleted file mode 100644 index cf703a4..0000000 --- a/frontend/src/App.test.js +++ /dev/null @@ -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( - - - - ); - - expect(getByText(/learn/i)).toBeInTheDocument(); -}); diff --git a/frontend/src/Main/Main.css b/frontend/src/Main/Main.css new file mode 100644 index 0000000..06cc17c --- /dev/null +++ b/frontend/src/Main/Main.css @@ -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 { + + +} diff --git a/frontend/src/Main/Main.js b/frontend/src/Main/Main.js new file mode 100644 index 0000000..8545836 --- /dev/null +++ b/frontend/src/Main/Main.js @@ -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 }) => ( + +
+
+ +) + +/* +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 ( + +
+
+
+
+ + + + +
{process.env.REACT_APP_SITE_NAME}
+ Listen + About +
+
+ +
+
+ + {children} +
+ ) + } +} +/* +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 ( + + + + + Home + + Systems + About + + + +
+
+
+
+ + + + + + + + + {process.env.REACT_APP_SITE_NAME} + + + + +
+ {children} +
+
+
+ ) + } +} +/* +MobileContainer.propTypes = { + children: PropTypes.node, +} +*/ +const ResponsiveContainer = ({ children }) => ( +
+ {children} + {children} +
+) + +// ---------------------------------------------------- +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 ( + <> + + +
+ + + + + { system && ( + + this.props.changeUrl("/system/" + system.shortName)}/> + + )} + + + + + + + + + + + + + + +
+ All The Calls +
+

Every call, on every talkgroup is recorded

+
+ +
+ + Go back in time +
+

+ Missed a call? Not a problem, everything is archived! +

+
+
+
+
+ + +
+ Don't just scan, hear it all! +
+

+ 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. +

+ + Get Involved + +
+ Want to record your local radio system? +
+

+ 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. +

+ + + +
+
+
+ + + + + + + + +
+ The End +
+
+ + + + +
+
+
+
+ +
+ ); +} + +} + +export default Main; diff --git a/frontend/src/Main/MainContainer.js b/frontend/src/Main/MainContainer.js new file mode 100644 index 0000000..8ba167c --- /dev/null +++ b/frontend/src/Main/MainContainer.js @@ -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) diff --git a/frontend/src/System/ListSystems.js b/frontend/src/System/ListSystems.js new file mode 100644 index 0000000..f5f8cf0 --- /dev/null +++ b/frontend/src/System/ListSystems.js @@ -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 ( +
+ + Home + About + + +
Radio Systems
+ + {systems.map((system) => + system.active&& this.props.changeUrl("/system/" + system.shortName)}/> + // this.props.changeUrl("/system/" + system.shortName)}/> + )} + +
+
+ ); + } +} + +export default ListSystems; diff --git a/frontend/src/System/ListSystemsContainer.js b/frontend/src/System/ListSystemsContainer.js new file mode 100644 index 0000000..9052b1f --- /dev/null +++ b/frontend/src/System/ListSystemsContainer.js @@ -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) diff --git a/frontend/src/System/SystemCard.js b/frontend/src/System/SystemCard.js new file mode 100644 index 0000000..62bc2e5 --- /dev/null +++ b/frontend/src/System/SystemCard.js @@ -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 ( + + + {system.name} + {system.screenName && } + + + + + {location} + + + {clientCount &&
{clientCount}
} +
+ + {callAvg &&
{callAvg}
} +
+
+
+
+ ); + } +} + +export default SystemCard; diff --git a/frontend/src/System/system-actions.js b/frontend/src/System/system-actions.js new file mode 100644 index 0000000..03d7514 --- /dev/null +++ b/frontend/src/System/system-actions.js @@ -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); + } + }); + }; +}; +} diff --git a/frontend/src/System/system-constants.js b/frontend/src/System/system-constants.js new file mode 100644 index 0000000..e14527b --- /dev/null +++ b/frontend/src/System/system-constants.js @@ -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" diff --git a/frontend/src/System/system-reducer.js b/frontend/src/System/system-reducer.js new file mode 100644 index 0000000..e7a790b --- /dev/null +++ b/frontend/src/System/system-reducer.js @@ -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; diff --git a/frontend/src/index.js b/frontend/src/index.js index 1f0dcb3..7f8c092 100644 --- a/frontend/src/index.js +++ b/frontend/src/index.js @@ -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( { /* place ConnectedRouter under Provider */ } <> { /* your usual react-router v4/v5 routing */ } - ()} /> + + (
Miss
)} />
diff --git a/frontend/src/app/configureStore.js b/frontend/src/redux-router/configureStore.js similarity index 100% rename from frontend/src/app/configureStore.js rename to frontend/src/redux-router/configureStore.js diff --git a/frontend/src/app/reducers.js b/frontend/src/redux-router/reducers.js similarity index 76% rename from frontend/src/app/reducers.js rename to frontend/src/redux-router/reducers.js index b9a605b..7e1dd4e 100644 --- a/frontend/src/app/reducers.js +++ b/frontend/src/redux-router/reducers.js @@ -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 diff --git a/frontend/src/resources/DidactGothic-Regular.ttf b/frontend/src/resources/DidactGothic-Regular.ttf new file mode 100755 index 0000000..62bdba3 Binary files /dev/null and b/frontend/src/resources/DidactGothic-Regular.ttf differ diff --git a/frontend/src/resources/logo.png b/frontend/src/resources/logo.png new file mode 100644 index 0000000..b05d956 Binary files /dev/null and b/frontend/src/resources/logo.png differ diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 1c82f07..e025828 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -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: