From 5bfff7bb900ad1e7eb966cd7fec779245cb05982 Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Wed, 15 Mar 2023 22:35:34 -0400 Subject: [PATCH] Gettign going --- account/server/config/express.js | 2 +- account/server/config/passport.js | 11 +- account/server/controllers/systems.js | 98 +- admin/Dockerfile | 4 +- admin/package.json | 63 +- admin/server/config/express.js | 14 +- admin/server/config/passport.js | 11 +- admin/server/controllers/groups.js | 475 +- admin/server/controllers/systems.js | 179 +- admin/server/controllers/talkgroups.js | 426 +- admin/server/index.js | 8 +- admin/src/App/App.js | 47 +- admin/src/App/Restricted.js | 44 +- admin/src/Components/About.js | 6 +- admin/src/Group/group-actions.js | 2 +- admin/src/System/ListSystems.js | 29 +- admin/src/System/System.js | 969 +- admin/src/System/SystemCard.js | 46 +- admin/src/System/error-actions.js | 2 +- admin/src/System/system-actions.js | 2 +- admin/src/Talkgroups/talkgroup-actions.js | 6 +- admin/src/User/user-actions.js | 2 +- admin/src/features/api/apiSlice.js | 73 + admin/src/features/counter/Counter.js | 60 - admin/src/features/counter/Counter.module.css | 74 - admin/src/features/counter/counterSlice.js | 42 - admin/src/features/group/groupSlice.js | 15 + admin/src/features/user/userSlice.js | 81 + admin/src/index.js | 37 +- admin/src/redux-router/configureStore.js | 9 +- admin/src/redux-router/reducers.js | 11 +- admin/yarn.lock | 14691 ++++++++-------- frontend/src/index.js | 2 +- mongo/Dockerfile | 12 +- 34 files changed, 8327 insertions(+), 9226 deletions(-) create mode 100644 admin/src/features/api/apiSlice.js delete mode 100644 admin/src/features/counter/Counter.js delete mode 100644 admin/src/features/counter/Counter.module.css delete mode 100644 admin/src/features/counter/counterSlice.js create mode 100644 admin/src/features/group/groupSlice.js create mode 100644 admin/src/features/user/userSlice.js diff --git a/account/server/config/express.js b/account/server/config/express.js index e040907..b1f620c 100644 --- a/account/server/config/express.js +++ b/account/server/config/express.js @@ -11,7 +11,7 @@ var backend_server = process.env['REACT_APP_BACKEND_SERVER'] != null ? process.e var frontend_server = process.env['REACT_APP_FRONTEND_SERVER'] != null ? process.env['REACT_APP_FRONTEND_SERVER'] : 'https://openmhz.com'; var socket_server = process.env['REACT_APP_SOCKET_SERVER'] != null ? process.env['REACT_APP_SOCKET_SERVER'] : 'wss://socket.openmhz.com'; //'https://s3.amazonaws.com/robotastic'; var account_server = process.env['REACT_APP_ACCOUNT_SERVER'] != null ? process.env['REACT_APP_ACCOUNT_SERVER'] : 'https://account.openmhz.com'; //'https://s3.amazonaws.com/robotastic'; -var dev_server = frontend_server + ":3000" +var dev_server = "http://admin.openmhz.test:3000" module.exports = function(app, passport) { app.set("port", 3009) diff --git a/account/server/config/passport.js b/account/server/config/passport.js index ea3b8d9..36f72bb 100644 --- a/account/server/config/passport.js +++ b/account/server/config/passport.js @@ -14,10 +14,13 @@ module.exports = function (app, passport) { done(null, user.id) }) - passport.deserializeUser((id, done) => { - User.findById(id, (err, user) => { - done(err, user) - }) + passport.deserializeUser(async (id, done) => { + const user = await User.findById(id).exec(); + if (user) { + done(null,user); + } else { + done("User not found", null); + } }) // use the following strategies diff --git a/account/server/controllers/systems.js b/account/server/controllers/systems.js index 00caea6..8c6a83b 100644 --- a/account/server/controllers/systems.js +++ b/account/server/controllers/systems.js @@ -5,58 +5,52 @@ const System = require("../models/system"); // ------------------------------------------- -exports.getUserSystems = function(_id) { - console.log("Listing Systems for: " + _id); - System.find( - { - userId: mongoose.Types.ObjectId(_id) - }, - function(err, systems) { - if (err) { - console.error("Error - ListSystems: " + err); - return({ success: false, message: err }); - } - - - var returnSys = systems.map(obj => { - var rObj = (({ - name, - shortName, - description, - systemType, - city, - state, - county, - country, - userId, - key, - planType, - showScreenName - }) => ({ - name, - shortName, - description, - systemType, - city, - state, - county, - country, - userId, - key, - planType, - showScreenName - }))(obj); - rObj.id = obj._id; - return rObj; - }); - - - return({ success: true, systems: returnSys }); - } - ); +exports.getUserSystems = async function (_id) { + console.log("Listing Systems for: " + _id); + const userId = new mongoose.Types.ObjectId(req.user._id); + const systems = await System.find({ userId: userId }); + if (systems == null) { + return ({ success: false, message: err }); + } + + var returnSys = systems.map(obj => { + var rObj = (({ + name, + shortName, + description, + systemType, + city, + state, + county, + country, + userId, + key, + planType, + showScreenName + }) => ({ + name, + shortName, + description, + systemType, + city, + state, + county, + country, + userId, + key, + planType, + showScreenName + }))(obj); + rObj.id = obj._id; + return rObj; + }); + + + return ({ success: true, systems: returnSys }); } -exports.listSystems = function(req, res, next) { - return listSystems(req.user._id); - } + +exports.listSystems = function (req, res, next) { + return listSystems(req.user._id); +} diff --git a/admin/Dockerfile b/admin/Dockerfile index 742b3fd..0b20871 100644 --- a/admin/Dockerfile +++ b/admin/Dockerfile @@ -1,5 +1,5 @@ # build environment -FROM node:13.12.0-alpine as build +FROM node:19-alpine3.16 as build WORKDIR /app ENV PATH /app/node_modules/.bin:$PATH ARG REACT_APP_BACKEND_SERVER @@ -15,7 +15,7 @@ COPY . ./ RUN npm run build # production environment -FROM node:13.12.0-alpine +FROM node:19-alpine3.16 RUN mkdir -p /app/public COPY ./package.json /tmp RUN cd /tmp && npm install diff --git a/admin/package.json b/admin/package.json index bf6ceb4..17c4e63 100644 --- a/admin/package.json +++ b/admin/package.json @@ -3,41 +3,42 @@ "version": "0.1.0", "private": true, "dependencies": { - "@visx/axis": "1.4.0", - "@visx/curve": "1.0.0", - "@visx/glyph": "1.0.0", - "@visx/group": "1.0.0", - "@visx/legend": "1.4.0", - "@visx/responsive": "1.3.0", - "@visx/scale": "1.4.0", - "@visx/shape": "1.4.0", - "bcrypt": "5.0.0", + "@lagunovsky/redux-react-router": "^4.3.0", + "@visx/axis": "3.0.1", + "@visx/curve": "3.0.0", + "@visx/glyph": "3.0.0", + "@visx/group": "3.0.0", + "@visx/legend": "3.0.0", + "@visx/responsive": "3.0.0", + "@visx/scale": "3.0.0", + "@visx/shape": "3.0.0", + "bcrypt": "5.1.0", "bcryptjs": "2.4.3", - "connect-mongo": "3.2.0", - "csv-parse": "4.14.2", - "d3-time-format": "3.0.0", - "express": "4.17.1", - "express-session": "1.17.1", - "mongoose": "5.11.11", - "multer": "1.4.2", - "passport": "0.4.1", + "connect-mongo": "^4.6.0", + "csv-parse": "5.3.6", + "d3-time-format": "4.1.0", + "express": "4.18.2", + "express-session": "1.17.3", + "history": "^5.3.0", + "mongoose": "7.0.0", + "multer": "1.4.5-lts.1", + "passport": "0.6.0", "passport-local": "1.0.0" }, "devDependencies": { - "@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", - "axios": "0.21.1", - "connected-react-router": "6.8.0", - "react": "^17.0.1", - "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", - "semantic-ui-css": "2.4.1", - "semantic-ui-react": "2.0.1" + "@reduxjs/toolkit": "^1.9.3", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^14.0.0", + "@testing-library/user-event": "^14.4.3", + "axios": "1.3.4", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-redux": "^8.0.5", + "react-router-dom": "6.8.2", + "react-scripts": "5.0.1", + "redux-thunk": "2.4.2", + "semantic-ui-css": "2.5.0", + "semantic-ui-react": "2.1.4" }, "scripts": { "start": "react-scripts start", diff --git a/admin/server/config/express.js b/admin/server/config/express.js index b54deef..0e517c3 100644 --- a/admin/server/config/express.js +++ b/admin/server/config/express.js @@ -2,16 +2,15 @@ const path = require("path"); const express = require("express"); const session = require("express-session"); const bodyParser = require("body-parser"); -const connectMongo = require("connect-mongo"); +const MongoStore = require("connect-mongo"); const secrets = require("./secrets"); -const MongoStore = connectMongo(session) var cookie_domain = process.env['REACT_APP_COOKIE_DOMAIN'] != null ? process.env['REACT_APP_COOKIE_DOMAIN'] : '.openmhz.com'; //'https://s3.amazonaws.com/robotastic'; var backend_server = process.env['REACT_APP_BACKEND_SERVER'] != null ? process.env['REACT_APP_BACKEND_SERVER'] : 'https://api.openmhz.com'; var frontend_server = process.env['REACT_APP_FRONTEND_SERVER'] != null ? process.env['REACT_APP_FRONTEND_SERVER'] : 'https://openmhz.com'; var socket_server = process.env['REACT_APP_SOCKET_SERVER'] != null ? process.env['REACT_APP_SOCKET_SERVER'] : 'wss://socket.openmhz.com'; //'https://s3.amazonaws.com/robotastic'; var account_server = process.env['REACT_APP_ACCOUNT_SERVER'] != null ? process.env['REACT_APP_ACCOUNT_SERVER'] : 'https://account.openmhz.com'; //'https://s3.amazonaws.com/robotastic'; -var dev_server = frontend_server + ":3000" +var dev_server = "http://admin.openmhz.test:3000" module.exports = function(app, passport) { app.set("port", 3008) @@ -36,9 +35,12 @@ module.exports = function(app, passport) { secure: false, domain: cookie_domain }, - store: new MongoStore({ - url: secrets.db, - autoReconnect: true + store: MongoStore.create({ + mongoUrl: secrets.db, + autoReconnect: true, + autoRemove: 'interval', + autoRemoveInterval: 240, + touchAfter: 24 * 3600 // time period in seconds }) } diff --git a/admin/server/config/passport.js b/admin/server/config/passport.js index 44674ca..291d560 100644 --- a/admin/server/config/passport.js +++ b/admin/server/config/passport.js @@ -14,10 +14,13 @@ module.exports = function (app, passport) { done(null, user.id) }) - passport.deserializeUser((id, done) => { - User.findById(id, (err, user) => { - done(err, user) - }) + passport.deserializeUser(async (id, done) => { + const user = await User.findById(id).exec(); + if (user) { + done(null,user); + } else { + done("User not found", null); + } }) diff --git a/admin/server/controllers/groups.js b/admin/server/controllers/groups.js index 42c3411..d001b15 100644 --- a/admin/server/controllers/groups.js +++ b/admin/server/controllers/groups.js @@ -4,286 +4,241 @@ const mongoose = require("mongoose"); //router.get('/system/:shortName/group/:groupId?', isLoggedIn, function(req, res) { -exports.getGroups = function(req, res, next) { - process.nextTick(function() { - System.findOne( - { - shortName: req.params.shortName.toLowerCase() - }, - function(err, system) { - if (err) { - console.error(err); - res.json({ success: false, message: err }); - return; - } - if (!system) { - console.error(err); - res.json({ - success: false, - message: "That Short Name does not exist." - }); - return; - } - if (!system.userId.equals(req.user._id)) { - res.json({ - success: false, - message: "You are not the user associated with this system." - }); - return; - } +exports.getGroups = async function (req, res, next) { + process.nextTick(async function () { + const system = await System.findOne({ shortName: req.params.shortName.toLowerCase() }); + if (!system) { + res.status(404); + res.json({ success: false }); + return; + } - if (req.params.groupId) { - var groupId = req.params.groupId.toLowerCase(); + if (!system.userId.equals(req.user._id)) { + res.status(401) + res.json({ + success: false, + message: "You are not the user associated with this system." + }); + return; + } - Group.findOne( - { - _id: new mongoose.Types.ObjectId(groupId), - shortName: req.params.shortName.toLowerCase() - }, - { sort: { position: -1 } }, - function(err, group) { - if (err) { - res.json({ - success: false, - message: err - }); - return; - } else { - res.json({ - success: true, - group: group - }); - return; - } - } - ); - } else { - Group.find( - { - shortName: req.params.shortName.toLowerCase() - }).sort("position").exec( - function(err, groups) { - if (err) { - res.json({ - success: false, - message: err - }); - return; - } else { - res.json({ - success: true, - groups: groups - }); - return; - } - } - ); - } + if (req.params.groupId) { + var groupId = req.params.groupId.toLowerCase(); + + const group = await Group.findOne( + { + _id: new mongoose.Types.ObjectId(groupId), + shortName: req.params.shortName.toLowerCase() + }, + { sort: { position: -1 } }); + if (!group) { + res.status(404); + res.json({ success: false }); + return; + + } else { + res.json(group); + return; } - ); - }); + } else { + const group = await Group.findOne( + { + shortName: req.params.shortName.toLowerCase() + }).sort("position").exec(); + if (!group) { + res.status(404); + res.json({ success: false }); + return; + + } else { + let result = group; + if (!Array.isArray(group)) { + result = [group] + } + res.json(result); + return; + } + } + } + ); }; -exports.deleteGroup = function(req, res, next) { -//router.get('/system/:shortName/remove_group/:groupId', isLoggedIn, function(req, res) { - System.findOne({ - 'shortName': req.params.shortName.toLowerCase() - }, function(err, system) { +exports.deleteGroup = function (req, res, next) { + //router.get('/system/:shortName/remove_group/:groupId', isLoggedIn, function(req, res) { + System.findOne({ + 'shortName': req.params.shortName.toLowerCase() + }, function (err, system) { + if (err) { + console.error(err); + res.json({ success: false, message: err }); + return; + } + if (!system) { + console.error(err); + res.json({ + success: false, + message: "That Short Name does not exist." + }); + return; + } + if (!system.userId.equals(req.user._id)) { + res.json({ + success: false, + message: "You are not the user associated with this system." + }); + return; + } + Group.findOneAndRemove({ + shortName: req.params.shortName.toLowerCase(), + '_id': new mongoose.Types.ObjectId(req.params.groupId) + }, function (err) { + if (err) { - console.error(err); - res.json({ success: false, message: err }); - return; - } - if (!system) { - console.error(err); res.json({ success: false, - message: "That Short Name does not exist." + message: err }); return; - } - if (!system.userId.equals(req.user._id)) { - res.json({ - success: false, - message: "You are not the user associated with this system." - }); - return; - } - Group.findOneAndRemove({ - shortName: req.params.shortName.toLowerCase(), - '_id': new mongoose.Types.ObjectId(req.params.groupId) - }, function(err) { - - if (err) { - res.json({ - success: false, - message: err - }); - return; - } else { - res.json({ - success: true - }); - return; - } - // removed! - }); - - }); -}; - -exports.reorderGroups = function(req, res, next) { - //router.post('/system/:shortName/group_order', isLoggedIn, function(req, res) { - process.nextTick(function() { - System.findOne( - { - shortName: req.params.shortName.toLowerCase() - }, - function(err, system) { - if (err) { - console.error(err); - res.json({ success: false, message: err }); - return; - } - if (!system) { - console.error(err); - res.json({ - success: false, - message: "That Short Name does not exist." - }); - return; - } - if (!system.userId.equals(req.user._id)) { - res.json({ - success: false, - message: "You are not the user associated with this system." - }); - return; - } - - var groupOrder = JSON.parse(req.body.groupOrder); - for (var i = 0; i < groupOrder.length; i++) { - - console.log("in group: " + groupOrder[i] + " position: " + i); - Group.findOneAndUpdate( - { - _id: new mongoose.Types.ObjectId(groupOrder[i]), - shortName: req.params.shortName.toLowerCase() - }, - { - position: i - }, - { - new: true, - upsert: false - }, - function(err, group) { - console.log("Save group: " + group._id + " position: " + group.position); - if (err) { - res.json({ - success: false, - message: err - }); - - console.log( - "Error: Group Order - " + - err + - " Shortname: " + - req.params.shortName.toLowerCase() - ); - return; - } - } - ); - } + } else { res.json({ success: true }); + return; } - ); + // removed! + }); + }); }; -exports.upsertGroup = function(req, res, next) { +exports.reorderGroups = function (req, res, next) { + //router.post('/system/:shortName/group_order', isLoggedIn, function(req, res) { + process.nextTick(async function () { + const system = await System.findOne({ shortName: req.params.shortName.toLowerCase() }); + + if (!system) { + res.status(404); + res.json({ + success: false, + message: "That Short Name does not exist." + }); + return; + } + if (!system.userId.equals(req.user._id)) { + res.status(401); + res.json({ + success: false, + message: "You are not the user associated with this system." + }); + return; + } + + var groupOrder = JSON.parse(req.body.groupOrder); + for (var i = 0; i < groupOrder.length; i++) { + + console.log("in group: " + groupOrder[i] + " position: " + i); + const group = await Group.findOneAndUpdate( + { + _id: new mongoose.Types.ObjectId(groupOrder[i]), + shortName: req.params.shortName.toLowerCase() + }, + { + position: i + }, + { + new: true, + upsert: false + }); + if (!group) { + res.status(404) + res.json({ + success: false, + message: err + }); + + console.log( + "Error: Group Order - Shortname: " + + req.params.shortName.toLowerCase() + ); + return; + } + } + res.json({ + success: true + }); + } + ); +}; + +exports.upsertGroup = function (req, res, next) { //router.post('/system/:shortName/group/:groupId?', isLoggedIn, function(req, res) { - process.nextTick(function() { - System.findOne( + process.nextTick(async function () { + let system = System.findOne({ shortName: req.params.shortName.toLowerCase() }); + + if (!system) { + res.status(404); + res.json({ + success: false, + message: "That Short Name does not exist." + }); + return; + } + if (!system.userId.equals(req.user._id)) { + res.status(401); + res.json({ + success: false, + message: "You are not the user associated with this system." + }); + return; + } + var message = ""; + var groupName = req.body.groupName.replace(/[^\w\s]/g, ""); + var talkgroups = JSON.parse(req.body.talkgroups); + + if (!talkgroups.length || !Array.isArray(talkgroups)) { + message = "Talkgroups need to be selected, group can not be empty "; + } + if (!groupName.length) { + message = message + "Group Name is required"; + } + + if (message.length) { + res.json({ + success: false, + message: message + }); + return; + } + // if we got here, that means that everything is good for updating/inserting + + var groupId = req.params.groupId; + + let group = Group.findOneAndUpdate( { + _id: new mongoose.Types.ObjectId(groupId), shortName: req.params.shortName.toLowerCase() }, - function(err, system) { - if (err) { - console.error(err); - res.json({ success: false, message: err }); - return; - } - if (!system) { - console.error(err); - res.json({ - success: false, - message: "That Short Name does not exist." - }); - return; - } - if (!system.userId.equals(req.user._id)) { - res.json({ - success: false, - message: "You are not the user associated with this system." - }); - return; - } - var message = ""; - var groupName = req.body.groupName.replace(/[^\w\s]/g, ""); - var talkgroups = JSON.parse(req.body.talkgroups); + { + groupName: groupName, + talkgroups: talkgroups + }, + { + new: true, + upsert: true + }); - if (!talkgroups.length || !Array.isArray(talkgroups)) { - message = "Talkgroups need to be selected, group can not be empty "; - } - if (!groupName.length) { - message = message + "Group Name is required"; - } - if (message.length) { - res.json({ - success: false, - message: message - }); - return; - } - // if we got here, that means that everything is good for updating/inserting - - var groupId = req.params.groupId; - - Group.findOneAndUpdate( - { - _id: new mongoose.Types.ObjectId(groupId), - shortName: req.params.shortName.toLowerCase() - }, - { - groupName: groupName, - talkgroups: talkgroups - }, - { - new: true, - upsert: true - }, - function(err, group) { - if (err) { - res.json({ - success: false, - message: err - }); - return; - } else { - res.json({ - success: true, - group: group - }); - return; - } - } - ); - } - ); - }); -}; + if (!group) { + res.status(500); + res.json({ + success: false, + message: err + }); + return; + } else { + res.json(group); + return; + } + } + ); +} diff --git a/admin/server/controllers/systems.js b/admin/server/controllers/systems.js index 6bc62e9..3d19819 100644 --- a/admin/server/controllers/systems.js +++ b/admin/server/controllers/systems.js @@ -12,91 +12,76 @@ exports.isLoggedIn = function (req, res, next) { // ------------------------------------------- -exports.listSystems = function (req, res, next) { +exports.listSystems = async function (req, res, next) { console.log("Listing Systems for: " + req.user._id); - System.find({ - userId: mongoose.Types.ObjectId(req.user._id) - }, - function (err, systems) { - if (err) { - console.error("Error - ListSystems: " + err); - res.json({ - success: false, - message: err - }); - return; - } + const userId = new mongoose.Types.ObjectId(req.user._id); + const systems = await System.find({ userId: userId }).exec(); + if (systems == null) { + res.status(400); + res.json({ success: false, message: err }); + return; + } - var shortNames = new Array(); - for (var i = 0; i < systems.length; i++) { - shortNames.push(systems[i].shortName); - } + let shortNames = new Array(); + for (var i = 0; i < systems.length; i++) { + shortNames.push(systems[i].shortName); + } - SystemStat.find({ - shortName: { - $in: shortNames - } - }, - function (err, stats) { - var returnSys = systems.map(obj => { - var rObj = (({ - name, - shortName, - description, - systemType, - city, - state, - county, - country, - userId, - key, - showScreenName, - ignoreUnknownTalkgroup - }) => ({ - name, - shortName, - description, - systemType, - city, - state, - county, - country, - userId, - key, - showScreenName, - ignoreUnknownTalkgroup - }))(obj); - if (obj.showScreenName) { - rObj.screenName = req.user.screenName; - } else { - rObj.screenName = null; - } - rObj.id = obj._id; - return rObj; - }); - var sys_stats = {} - var MS_PER_MINUTE = 60000; - var now = new Date(); - for (var i = 0; i < stats.length; i++) { - sys_stats[stats[i].shortName] = {}; + const stats = await SystemStat.find({ shortName: { $in: shortNames } }).exec(); - sys_stats[stats[i].shortName].callTotals = stats[i].callTotals; - sys_stats[stats[i].shortName].errorTotals = stats[i].errorTotals; - sys_stats[stats[i].shortName].errorStats = stats[i].errorStats; - sys_stats[stats[i].shortName].usageBytes = stats[i].usageBytes; - sys_stats[stats[i].shortName].usageMb = stats[i].usageMb; - } - - res.json({ - success: true, - systems: returnSys, - stats: sys_stats - }); - return; - } - ); + let returnSys = systems.map(obj => { + var rObj = (({ + name, + shortName, + description, + systemType, + city, + state, + county, + country, + userId, + key, + showScreenName, + ignoreUnknownTalkgroup + }) => ({ + name, + shortName, + description, + systemType, + city, + state, + county, + country, + userId, + key, + showScreenName, + ignoreUnknownTalkgroup + }))(obj); + if (obj.showScreenName) { + rObj.screenName = req.user.screenName; + } else { + rObj.screenName = null; } - ); + rObj.id = obj._id; + return rObj; + }); + var sys_stats = {} + for (var i = 0; i < stats.length; i++) { + sys_stats[stats[i].shortName] = {}; + + sys_stats[stats[i].shortName].callTotals = stats[i].callTotals; + sys_stats[stats[i].shortName].errorTotals = stats[i].errorTotals; + sys_stats[stats[i].shortName].errorStats = stats[i].errorStats; + sys_stats[stats[i].shortName].usageBytes = stats[i].usageBytes; + sys_stats[stats[i].shortName].usageMb = stats[i].usageMb; + } + + res.json({ + success: true, + systems: returnSys, + stats: sys_stats + }); + return; }; function remove_system(shortName) { @@ -115,8 +100,8 @@ function remove_system(shortName) { }); */ System.remove({ - shortName: shortName - }, + shortName: shortName + }, function (err) { if (err) return console.error(err); // removed! @@ -124,8 +109,8 @@ function remove_system(shortName) { ); Talkgroup.remove({ - shortName: shortName - }, + shortName: shortName + }, function (err) { if (err) return console.error(err); // removed! @@ -133,8 +118,8 @@ function remove_system(shortName) { ); Group.remove({ - shortName: shortName - }, + shortName: shortName + }, function (err) { if (err) return console.error(err); // removed! @@ -145,8 +130,8 @@ function remove_system(shortName) { exports.deleteSystem = function (req, res, next) { //router.get('/delete_system/:shortName', isLoggedIn, function(req, res) { System.findOne({ - shortName: req.params.shortName.toLowerCase() - }, + shortName: req.params.shortName.toLowerCase() + }, function (err, system) { if (err) { res.json({ @@ -224,7 +209,7 @@ exports.uniqueShortName = async function (req, res, next) { var shortName = res.locals.shortName; if (typeof shortName == 'undefined') { - console.error("locals: " + res.locals.shortName + " body: " + req.body.shortName ) + console.error("locals: " + res.locals.shortName + " body: " + req.body.shortName) console.error("ShortName is not in res.local, pulling from req.body instead") shortName = req.body.shortName; } @@ -299,7 +284,7 @@ exports.updateSystem = async function (req, res, next) { userId, key, showScreenName, - ignoreUnknownTalkgroup + ignoreUnknownTalkgroup }) => ({ name, shortName, @@ -312,7 +297,7 @@ exports.updateSystem = async function (req, res, next) { userId, key, showScreenName, - ignoreUnknownTalkgroup + ignoreUnknownTalkgroup }))(res.locals.system); returnSys.id = res.locals.system._id; res.json({ @@ -329,7 +314,7 @@ exports.updateSystem = async function (req, res, next) { exports.validateSystem = async function (req, res, next) { try { res.locals.showScreenName = req.body.showScreenName; - res.locals.ignoreUnknownTalkgroup = req.body.ignoreUnknownTalkgroup ; + res.locals.ignoreUnknownTalkgroup = req.body.ignoreUnknownTalkgroup; if (!req.body.name || (req.body.name.length < 2)) { console.error("ERROR: Validate System - req.body.name"); res.json({ @@ -457,7 +442,7 @@ exports.createSystem = async function (req, res, next) { county, country, showScreenName, - ignoreUnknownTalkgroup + ignoreUnknownTalkgroup }) => ({ name, shortName, @@ -468,10 +453,10 @@ exports.createSystem = async function (req, res, next) { county, country, showScreenName, - ignoreUnknownTalkgroup + ignoreUnknownTalkgroup }))(res.locals); system.key = key; - system.userId = mongoose.Types.ObjectId(req.user._id); + system.userId = new mongoose.Types.ObjectId(req.user._id); System.create(system, function (err, newSys) { if (err) { console.error(err); @@ -492,7 +477,7 @@ exports.createSystem = async function (req, res, next) { country, userId, showScreenName, - ignoreUnknownTalkgroup , + ignoreUnknownTalkgroup, key }) => ({ name, @@ -505,7 +490,7 @@ exports.createSystem = async function (req, res, next) { country, userId, showScreenName, - ignoreUnknownTalkgroup , + ignoreUnknownTalkgroup, key }))(newSys); returnSys.id = newSys._id; diff --git a/admin/server/controllers/talkgroups.js b/admin/server/controllers/talkgroups.js index 04376d3..27fc974 100644 --- a/admin/server/controllers/talkgroups.js +++ b/admin/server/controllers/talkgroups.js @@ -5,251 +5,217 @@ const fs = require('fs-extra'); const crypto = require("crypto"); var parse = require('csv-parse'); -exports.isLoggedIn = function(req, res, next) { +exports.isLoggedIn = function (req, res, next) { if (req.isAuthenticated()) return next(); res.redirect(account_server + "/login"); }; //router.get("/tg_export/:shortName", isLoggedIn, function(req, res) { -exports.exportTalkgroups = function(req, res, next) { - process.nextTick(function() { - System.findOne( - { - shortName: req.params.shortName.toLowerCase() - }, - function(err, system) { - if (err) { - console.error(err); - res.json({ success: false, message: err }); - return; - } - if (!system) { - console.error(err); - res.json({ - success: false, - message: "That Short Name does not exist." - }); - return; - } - if (!system.userId.equals(req.user._id)) { - res.json({ - success: false, - message: "You are not the user associated with this system." - }); - return; - } - Talkgroup.find( - { - shortName: req.params.shortName.toLowerCase() - }, - function(err, talkgroups) { - if (err) { - console.error(err); - res.json({ success: false, message: err }); - return; - } - if (!talkgroups || !Array.isArray(talkgroups)) { - console.error(err); - res.json({ - success: false, - message: "Talkgroups were not found." - }); - return; - } - res.statusCode = 200; - res.setHeader("Content-Type", "text/csv"); - talkgroups.forEach(function(item) { - /* res.write('"' + item.num + '", "' - + item.mode + '", "' - + item.alpha + '", "' - + item.description + '", "' - + item.tag + '", "' - + item.group + '", "' - + item.priority+ '"\r\n');*/ - if (item) { - var sending = ""; - sending = item.num + ", "; - if (item.mode) { - sending = sending + item.mode.toString().replace(/\,/g, "") + ", "; - } else { - sending = sending + " ,"; - } - if (item.alpa) { - sending = sending + item.alpha.toString().replace(/\,/g, "") + ", "; - } else { - sending = sending + " ,"; - } - if (item.description) { - sending = sending + item.description.toString().replace(/\,/g, "") + ", "; - } else { - sending = sending + " ,"; - } - if (item.tag) { - sending = sending + item.tag.toString().replace(/\,/g, "") + ", "; - } else { - sending = sending + " ,"; - } - if (item.group) { - sending = sending + item.group.toString().replace(/\,/g, "") + ", "; - } else { - sending = sending + " ,"; - } - if (item.priority) { - sending = sending + item.priority.toString().replace(/\,/g, "") + "\r\n"; - } else { - sending = sending + "\r\n"; - } - res.write(sending); - - } - }); - - res.end(); - } - ); - } - ); - }); -}; - -function csv_import(shortName, filename, callback) { - var talkgroups = []; - Talkgroup.remove( - { - shortName: shortName - }, - function(err) { - if (err) { - console.error("Error: csv import: " + err); - callback(err, null); - } else { - var parser = parse( - { - columns: [ - "num", - "mode", - "alpha", - "description", - "tag", - "group", - "priority" - ] - }, - async function(err, data) { - if (err) { - console.error("Error: csv import 2: " + err); - callback(err, null); - } else { - var response = []; - for (var i = 0; i < data.length; i++) { - var row = data[i]; - row.num = parseInt(row.num); - row.tag = row.tag.toLowerCase(); - row.group = row.group.toLowerCase(); - var newTg = new Talkgroup(); - newTg.num = row.num; - newTg.alpha = row.alpha; - newTg.mode = row.mode; - newTg.description = row.description; - newTg.tag = row.tag; - newTg.group = row.group; - newTg.priority = row.priority; - newTg.shortName = shortName; - - await newTg.save(function(err) { - if (err) { - console.log("Error: CSV import: " + err); - callback(err, null); - } - }); - - response.push(row); - } - callback(null, response); - } - } - ); - } - fs.createReadStream(filename).pipe(parser); - // removed! +exports.exportTalkgroups = function (req, res, next) { + process.nextTick(async function () { + const system = await System.findOne({ shortName: req.params.shortName.toLowerCase() }); + if (!system) { + res.status(404); + res.json({ + success: false, + message: "That Short Name does not exist." + }); + return; } + if (!system.userId.equals(req.user._id)) { + res.status(401); + res.json({ + success: false, + message: "You are not the user associated with this system." + }); + return; + } + const talkgroups = await Talkgroup.find({ shortName: req.params.shortName.toLowerCase() }) + + if (!talkgroups || !Array.isArray(talkgroups)) { + console.error(err); + res.json({ + success: false, + message: "Talkgroups were not found." + }); + return; + } + res.statusCode = 200; + res.setHeader("Content-Type", "text/csv"); + talkgroups.forEach(function (item) { + /* res.write('"' + item.num + '", "' + + item.mode + '", "' + + item.alpha + '", "' + + item.description + '", "' + + item.tag + '", "' + + item.group + '", "' + + item.priority+ '"\r\n');*/ + if (item) { + var sending = ""; + sending = item.num + ", "; + if (item.mode) { + sending = sending + item.mode.toString().replace(/\,/g, "") + ", "; + } else { + sending = sending + " ,"; + } + if (item.alpa) { + sending = sending + item.alpha.toString().replace(/\,/g, "") + ", "; + } else { + sending = sending + " ,"; + } + if (item.description) { + sending = sending + item.description.toString().replace(/\,/g, "") + ", "; + } else { + sending = sending + " ,"; + } + if (item.tag) { + sending = sending + item.tag.toString().replace(/\,/g, "") + ", "; + } else { + sending = sending + " ,"; + } + if (item.group) { + sending = sending + item.group.toString().replace(/\,/g, "") + ", "; + } else { + sending = sending + " ,"; + } + if (item.priority) { + sending = sending + item.priority.toString().replace(/\,/g, "") + "\r\n"; + } else { + sending = sending + "\r\n"; + } + res.write(sending); + + } + }); + + res.end(); + } ); } -//router.post("/tg_import/:shortName", isLoggedIn, upload.single('file'), function(req, res, next) { -exports.importTalkgroups = function(req, res, next) { - process.nextTick(function() { - System.findOne( - { - shortName: req.params.shortName.toLowerCase() - }, - function(err, system) { - if (err) { - console.error("Error - importTalkgroups: " + err); - res.json({ success: false, message: err }); - return; - } - if (!system) { - console.error("Error - importTalkgroups: System not found - " + req.params.shortName.toLowerCase()); - res.json({ - success: false, - message: "That Short Name does not exist." - }); - return; - } - if (!system.userId.equals(req.user._id)) { - console.error("Error - importTalkgroups: you are not the user for hte system: " + req.user._id); - res.json({ - success: false, - message: "You are not the user associated with this system." - }); - return; - } - if (!req.file || req.file.size === 0) { - res.json({ success: false, message: "Please select a file." }); - return; - } +async function csv_import(shortName, filename, callback) { + var talkgroups = []; + const count = await Talkgroup.deleteMany({ shortName: shortName }); - fs.exists(req.file.path, function(exists) { - if (exists) { - csv_import(system.shortName, req.file.path, function(err, data) { - if (err) { - console.error("Erorr - CSV import, callback: " + err); - res.json({ success: false, message: err }); - res.end(); - return; - } else { - res.json({ success: true, talkgroups: data }); - return; - } - }); + var parser = parse( + { + columns: [ + "num", + "mode", + "alpha", + "description", + "tag", + "group", + "priority" + ] + }, + async function (err, data) { + if (err) { + console.error("Error: csv import 2: " + err); + callback(err, null); + } else { + var response = []; + for (var i = 0; i < data.length; i++) { + var row = data[i]; + row.num = parseInt(row.num); + row.tag = row.tag.toLowerCase(); + row.group = row.group.toLowerCase(); + var newTg = new Talkgroup(); + newTg.num = row.num; + newTg.alpha = row.alpha; + newTg.mode = row.mode; + newTg.description = row.description; + newTg.tag = row.tag; + newTg.group = row.group; + newTg.priority = row.priority; + newTg.shortName = shortName; + + await newTg.save().catch(err => { + console.log("Error: CSV import: " + err); + callback(err, null); + }); + + response.push(row); + } + callback(null, response); + } + } + ); + fs.createReadStream(filename).pipe(parser); +} + + +//router.post("/tg_import/:shortName", isLoggedIn, upload.single('file'), function(req, res, next) { +exports.importTalkgroups = function (req, res, next) { + process.nextTick(async function () { + const system = System.findOne({ shortName: req.params.shortName.toLowerCase() }).catch(err => { + res.status(500); + console.error("Error - importTalkgroups: " + err); + res.json({ success: false, message: err }); + return; + }); + + if (!system) { + console.error("Error - importTalkgroups: System not found - " + req.params.shortName.toLowerCase()); + res.status(404); + res.json({ + success: false, + message: "That Short Name does not exist." + }); + return; + } + if (!system.userId.equals(req.user._id)) { + console.error("Error - importTalkgroups: you are not the user for hte system: " + req.user._id); + res.status(401); + res.json({ + success: false, + message: "You are not the user associated with this system." + }); + return; + } + if (!req.file || req.file.size === 0) { + res.status(500); + res.json({ success: false, message: "Please select a file." }); + return; + } + + fs.exists(req.file.path, function (exists) { + if (exists) { + csv_import(system.shortName, req.file.path, function (err, data) { + if (err) { + console.error("Erorr - CSV import, callback: " + err); + res.status(500); + res.json({ success: false, message: err }); + res.end(); + return; } else { - console.error("Error - importTalkgroups: no file"); - res.end( - "Well, there is no magic for those who don’t believe in it!" - ); + res.json( data ); + return; } }); + } else { + res.status(500); + console.error("Error - importTalkgroups: no file"); + res.end( + "Well, there is no magic for those who don’t believe in it!" + ); } - ); - }); + }); + } + ); }; + // ------------------------------------------- -exports.fetchTalkgroups = function(req, res, next) { - Talkgroup.find( - { - shortName: req.params.shortName.toLowerCase() - }, - function(err, talkgroups) { - if (err) { - console.error(err); - res.json({ success: false, message: err }); - return; - } - res.json({ success: true, talkgroups: talkgroups }); - return; - } - ); -}; +exports.fetchTalkgroups = async function (req, res, next) { + const talkgroups = await Talkgroup.find({ shortName: req.params.shortName.toLowerCase() }).catch(err => { + console.error(err); + res.status(500); + res.json({ success: false, message: err }); + return; + }); + + res.json(talkgroups ); + return; +} diff --git a/admin/server/index.js b/admin/server/index.js index 17c4aa0..917155c 100644 --- a/admin/server/index.js +++ b/admin/server/index.js @@ -42,13 +42,7 @@ async function connect() { // Connect to a MongoDB server running on 'localhost:27017' and use the // 'test' database. - await mongoose.connect(secrets.db, { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true }, (err, res) => { - if (err) { - console.log(`Mongoose - Error connecting to ${secrets.db}. ${err}`) - } else { - console.log(`Mongoose Successfully connected to ${secrets.db}.`) - } - }) + await mongoose.connect(secrets.db, { useNewUrlParser: true, useUnifiedTopology: true }); console.log("All Done"); } connect(); diff --git a/admin/src/App/App.js b/admin/src/App/App.js index 2f03f3b..b4fcbd3 100644 --- a/admin/src/App/App.js +++ b/admin/src/App/App.js @@ -1,15 +1,48 @@ -import React, { Component } from "react" +import React, { Component } from "react" import NavigationContainer from "./NavigationContainer" +import { Routes, Route } from 'react-router-dom'; -class App extends Component { - render() { - return( +import Restricted from "./Restricted" + +import About from "../Components/About" +import System from "../System/System" +import ListSystems from "../System/ListSystems" +import UpdateSystemContainer from "../System/UpdateSystemContainer" +import CreateSystemContainer from "../System/CreateSystemContainer" + + +const App = (params) => { + const {store} = params; + return (
- {this.props.children} + + } /> + } /> + + + } /> + } /> + (
Miss
)} /> +
) - } -} + /* + return ( +
+ + + } component={Restricted(About, store)} /> + + + + + + (
Miss
)} /> +
+
+ )*/ + +}; export default App diff --git a/admin/src/App/Restricted.js b/admin/src/App/Restricted.js index 36cc19f..1344a19 100644 --- a/admin/src/App/Restricted.js +++ b/admin/src/App/Restricted.js @@ -1,12 +1,46 @@ // in src/restricted.js -import React, { Component } from 'react'; -import { withRouter } from 'react-router-dom'; +//import React, { Component } from 'react'; +import React, { useEffect, useLayoutEffect, useState, useRef, useCallback, useMemo } from "react"; +import { useSelector, useDispatch } from 'react-redux' import * as types from "../User/user-constants"; import axios from "axios"; +import { + Routes, + Route, + Link, + Navigate, + Outlet, +} from 'react-router-dom'; +import { authenticateUser } from "../features/user/userSlice"; /** * Higher-order component (HOC) to wrap restricted pages */ + + +const Restricted = ({children }) => { + const { authenticated, hasAuthenticated } = useSelector((state) => state.user); + const dispatch = useDispatch(); + + useEffect(() => { + dispatch(authenticateUser({})); + },[]); + + useEffect(() => { + if (!authenticated) { + console.log("I loaded things and it is not good") + } + }, [hasAuthenticated]) + + if (authenticated) { + return children;; + } + return
+ +}; + +/* const restricted = (BaseComponent, store) => { + class Restricted extends Component { componentDidMount() { this.checkAuthentication(this.props); @@ -32,8 +66,6 @@ const restricted = (BaseComponent, store) => { }); } else { window.location = process.env.REACT_APP_ACCOUNT_SERVER + "/login?nextLocation=admin"; - /*history.replace({ pathname: '/login', - state: { nextPathname: params.location.pathname } });*/ } }) .catch(response => { @@ -51,4 +83,6 @@ const restricted = (BaseComponent, store) => { } return withRouter(Restricted); } -export default restricted \ No newline at end of file +*/ + +export default Restricted \ No newline at end of file diff --git a/admin/src/Components/About.js b/admin/src/Components/About.js index e7492dd..95cbc99 100644 --- a/admin/src/Components/About.js +++ b/admin/src/Components/About.js @@ -1,10 +1,10 @@ import React, { Component } from "react"; import { Container, Header } from "semantic-ui-react"; -class About extends Component { +const About = () => { + - render() { return (
Share the Air
@@ -18,7 +18,7 @@ class About extends Component {

- Luke {process.env.REACT_APP_ADMIN_EMAIL}

); - } + } export default About; diff --git a/admin/src/Group/group-actions.js b/admin/src/Group/group-actions.js index f23405a..8b9a90f 100644 --- a/admin/src/Group/group-actions.js +++ b/admin/src/Group/group-actions.js @@ -1,7 +1,7 @@ import axios from "axios"; //import { browserHistory } from "react-router" import * as types from "./group-constants"; -import { push } from 'connected-react-router'; +import { push } from '@lagunovsky/redux-react-router' // "Log In" action creators function beginCreateGroup() { diff --git a/admin/src/System/ListSystems.js b/admin/src/System/ListSystems.js index 4cb0472..1904065 100644 --- a/admin/src/System/ListSystems.js +++ b/admin/src/System/ListSystems.js @@ -1,4 +1,4 @@ -import React, { Component } from "react"; +import { Component, useRef } from "react"; import SystemCard from "./SystemCard"; import { Container, @@ -8,37 +8,40 @@ import { Icon, Button, } from "semantic-ui-react"; +import { useGetSystemsQuery, } from '../features/api/apiSlice' +import { useDispatch } from 'react-redux' +import { push } from '@lagunovsky/redux-react-router' // ---------------------------------------------------- -class ListSystems extends Component { - - state = { +const ListSystems = (props) => { + const { data, isSuccess } = useGetSystemsQuery(); + const dispatch = useDispatch(); + let systems = false; + if (isSuccess) { + systems = data.systems; } - 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 (
Radio Systems
- + - {systems.map((system) => - this.props.changeUrl("/system/" + system.shortName)}/> + {systems && + systems.map((system) => + dispatch(push("/system/" + system.shortName))}/> )}
); - } + } export default ListSystems; diff --git a/admin/src/System/System.js b/admin/src/System/System.js index f509a19..1689c89 100644 --- a/admin/src/System/System.js +++ b/admin/src/System/System.js @@ -1,5 +1,5 @@ -import React, {Component} from "react"; -import {Link} from "react-router-dom"; +import React, { useEffect, useLayoutEffect, useState, useRef, useCallback, useMemo } from "react"; +import { Link, useLocation, useParams, useNavigate } from 'react-router-dom'; import ListTalkgroups from "../Talkgroups/ListTalkgroups.js"; import MessageBox from "../Components/Message.js"; import ListGroups from "../Group/ListGroups.js"; @@ -8,6 +8,7 @@ import UpdatePermissionModal from "../Permission/UpdatePermissionModalContainer. import AddPermissionModal from "../Permission/AddPermissionModalContainer.js"; import ErrorChart from "./ResponsiveErrorChart" import CallChart from "./ResponsiveCallChart" +import { useGetSystemsQuery, useGetTalkgroupsQuery, useGetGroupsQuery, useGetErrorsQuery} from '../features/api/apiSlice' import { Button, Confirm, @@ -24,53 +25,23 @@ import { Label } from "semantic-ui-react"; +const System = (props) => { + const { shortName } = useParams(); + const { data: systemsData, isSuccess: isSystemsSuccess } = useGetSystemsQuery(); + const { data: talkgroupsData, isSuccess: isTalkgroupsSuccess } = useGetTalkgroupsQuery(shortName); + const { data: groupsData, isSuccess: isGroupsSuccess } = useGetGroupsQuery(shortName); + const { data: errorsData, isSuccess: isErrorsSuccess } = useGetErrorsQuery(shortName); + const [openSystemDeleteConfirm, setOpenSystemDeleteConfirm] = useState(false); + const [openPermissionDeleteConfirm, setOpenPermissionDeleteConfirm] = useState(false); + const [openMessage, setOpenMessage] = useState(false); + const [requestMessage, setRequestMessage] = useState(""); + const [groupVisible, setGroupVisible] = useState(false); + const [editGroupId, setEditGroupId] = useState(false); + const [errorData, setErrorData] = useState({}); + const [callData, setCallData] = useState({}); -class System extends Component { - constructor(props) { - super(props); - this.handleUpload = this.handleUpload.bind(this); - this.reorderGroup = this.reorderGroup.bind(this); - this.deleteGroup = this.deleteGroup.bind(this); - this.editGroup = this.editGroup.bind(this); - this.saveGroupOrder = this.saveGroupOrder.bind(this); - this.showSystemDeleteConfirm = this.showSystemDeleteConfirm.bind(this); - this.showPermissionDeleteConfirm = this.showPermissionDeleteConfirm.bind( - this - ); - this.updatePermission = this.updatePermission.bind(this); - this.handlePermissionDeleteConfirm = this.handlePermissionDeleteConfirm.bind( - this - ); - this.handlePermissionDeleteCancel = this.handlePermissionDeleteCancel.bind( - this - ); - this.handleSystemDeleteConfirm = this.handleSystemDeleteConfirm.bind(this); - this.handleSystemDeleteCancel = this.handleSystemDeleteCancel.bind(this); - this.handleUpdatePermissionClose = this.handleUpdatePermissionClose.bind( - this - ); - this.handleGroupToggle = this.handleGroupToggle.bind(this); - this.handleGroupClose = this.handleGroupClose.bind(this); - this.handleAddPermissionToggle = this.handleAddPermissionToggle.bind(this); - this.handleAddPermissionClose = this.handleAddPermissionClose.bind(this); - this.processErrors = this.processErrors.bind(this); - this.processStatistics = this.processStatistics.bind(this); - this.state = { - openSystemDeleteConfirm: false, - openPermissionDeleteConfirm: false, - openMessage: false, - requestMessage: "", - groupVisible: false, - editGroupId: false, - selectedPermission: false, - addPermissionVisible: false, - updatePermissionVisible: false, - updatePermissionId: false - }; - } - - processErrors(errors) { + const processErrors = (errors) => { var allData = []; var num = 0; @@ -111,9 +82,10 @@ class System extends Component { legend: legend }; - this.setState({ errorData: errorData }); - } - processStatistics(statistic) { + setErrorData(errorData); + }; + + const processStatistics = (statistic) => { var callTotals = []; var errorTotals = []; const now = new Date(); @@ -138,7 +110,7 @@ class System extends Component { maxValue = statistic.errorTotals[j]; errorTotals.push({ x: time, y: statistic.errorTotals[j] }); } - var callData = { + const callData = { minDate: minDate, maxDate: maxDate, minValue: minValue, @@ -147,503 +119,442 @@ class System extends Component { errorTotals: errorTotals }; - this.setState({ callData: callData }); + setCallData(callData); } - componentDidMount() { - this.props.systemActions.fetchSystems(); - this.props.talkgroupActions.fetchTalkgroups(this.props.shortName); - this.props.groupActions.fetchGroups(this.props.shortName); - this.props.errorActions.fetch(this.props.shortName); - this.props.permissionActions.fetch(this.props.shortName); - if (this.props.statistic) { - this.processStatistics(this.props.statistic); + + + /* + componentDidMount() { + this.props.systemActions.fetchSystems(); + this.props.talkgroupActions.fetchTalkgroups(this.props.shortName); + this.props.groupActions.fetchGroups(this.props.shortName); + this.props.errorActions.fetch(this.props.shortName); + if (this.props.statistic) { + this.processStatistics(this.props.statistic); + } + if (this.props.errors) { + this.processErrors(this.props.errors); + } } - if (this.props.errors) { - this.processErrors(this.props.errors); + + componentDidUpdate(prevProp) { + + // If we just received the error statistics for a system, for the first time, proccess them. + if (this.props.errors && !prevProp.errors) { + this.processErrors(this.props.errors); + } + // If we just received the call statistics for a system, for the first time, proccess them. + if (this.props.statistic && !prevProp.statistic) { + this.processStatistics(this.props.statistic); + } } - } - - componentDidUpdate(prevProp) { - - // If we just received the error statistics for a system, for the first time, proccess them. - if (this.props.errors && !prevProp.errors) { - this.processErrors(this.props.errors); + */ + + const editGroup = (groupId) => { + setEditGroupId(groupId) + setGroupVisible((state)=> !state) } - // If we just received the call statistics for a system, for the first time, proccess them. - if (this.props.statistic && !prevProp.statistic) { - this.processStatistics(this.props.statistic); + + const deleteGroup = (groupId) => { + //this.props.groupActions.deleteGroup(this.props.shortName, groupId); } - } + + const reorderGroup = (oldIndex, newIndex) => { + /*this.props.groupActions.reorderGroup( + this.props.shortName, + oldIndex, + newIndex + );*/ + } + + - updatePermission(permissionId) { - this.setState({ - updatePermissionId: permissionId, - updatePermissionVisible: !this.state.updatePermissionVisible - }); - } + - editGroup(groupId) { - this.setState({ - editGroupId: groupId, - groupVisible: !this.state.groupVisible - }); - } - - deleteGroup(groupId) { - this.props.groupActions.deleteGroup(this.props.shortName, groupId); - } - - reorderGroup(oldIndex, newIndex) { - this.props.groupActions.reorderGroup( - this.props.shortName, - oldIndex, - newIndex - ); - } - - handleUpdatePermissionClose(didUpdate) { - this.setState({ - updatePermissionVisible: !this.state.updatePermissionVisible, - updatePermissionId: false - }); - } - - handleAddPermissionClose(didUpdate) { - this.setState({ - addPermissionVisible: !this.state.addPermissionVisible - }); - } - - handleAddPermissionToggle = () => - this.setState({ - addPermissionVisible: !this.state.addPermissionVisible - }); - - handleGroupClose(didUpdate) { - this.setState({ - groupVisible: !this.state.groupVisible, - editGroupId: false - }); - } - handleGroupToggle = () => this.setState({ - editGroupId: false, - groupVisible: !this.state.groupVisible - }) - handleExport() { - this.props.talkgroupActions - .exportTalkgroups(this.props.system.shortName) - .then(requestMessage => { - if (requestMessage) { - // report to the user is there was a problem during registration - this.setState({ requestMessage }); - } - }); - } - - saveGroupOrder() { - const order = this.props.groups.map(x => x._id); - const data = { - groupOrder: JSON.stringify(order) + const handleGroupClose = () => { + setEditGroupId(false) + setGroupVisible(false) + } + + const handleGroupToggle = () => { + setEditGroupId(false) + setGroupVisible((state)=> !state) + } + + + + const handleExport = () => { + /* this.props.talkgroupActions + .exportTalkgroups(this.props.system.shortName) + .then(requestMessage => { + if (requestMessage) { + // report to the user is there was a problem during registration + this.setState({ requestMessage }); + } + });*/ + } + + const saveGroupOrder = () => { + /*const order = this.props.groups.map(x => x._id); + const data = { + groupOrder: JSON.stringify(order) + }; + this.props.groupActions + .saveGroupOrder(this.props.system.shortName, data) + .then(requestMessage => { + if (requestMessage) { + } + });*/ + } + + + const handleUpload = (file) => { + /*this.props.talkgroupActions + .importTalkgroups(this.props.system.shortName, file) + .then(requestMessage => { + if (requestMessage) { + // report to the user is there was a problem during registration + this.setState({ requestMessage }); + } + });*/ + } + + + + const handleSystemDeleteConfirm = () => { + setOpenSystemDeleteConfirm(false); + /* + this.props.systemActions + .deleteSystem(this.props.system.shortName) + .then(requestMessage => { + if (requestMessage) { + // report to the user is there was a problem during login + this.setState({ requestMessage: requestMessage, openMessage: true }); + } + });*/ }; - this.props.groupActions - .saveGroupOrder(this.props.system.shortName, data) - .then(requestMessage => { - if (requestMessage) { - } - }); + const handleSystemDeleteCancel = () => setOpenSystemDeleteConfirm(false); + + + let system = false; + if (isSystemsSuccess) { + system = systemsData.systems.find(sys=>sys.shortName == shortName); } - - handleUpload(file) { - this.props.talkgroupActions - .importTalkgroups(this.props.system.shortName, file) - .then(requestMessage => { - if (requestMessage) { - // report to the user is there was a problem during registration - this.setState({ requestMessage }); - } - }); + useEffect(() => { + if (isSystemsSuccess) { + processStatistics(systemsData.stats[shortName]) } + },[isSystemsSuccess]); - // https://github.com/Semantic-Org/Semantic-UI-React/issues/2103 + useEffect(() => { + if (isErrorsSuccess) { + processErrors(errorData) + } + },[isErrorsSuccess]); - showPermissionDeleteConfirm = permission => - this.setState({ - openPermissionDeleteConfirm: true, - selectedPermission: permission - }); - showSystemDeleteConfirm = () => - this.setState({ openSystemDeleteConfirm: true }); + let fileInput = null; + var location = ""; + var example = ""; + var groupRender = () => { }; - handlePermissionDeleteConfirm = permissionId => { - this.setState({ openPermissionDeleteConfirm: false }); - this.props.permissionActions - .deletePermission({ - shortName: this.props.system.shortName, - permissionId: this.state.selectedPermission._id - }) - .then(requestMessage => { - if (requestMessage) { - // report to the user is there was a problem during login - this.setState({ requestMessage: requestMessage, openMessage: true }); - } - }); - }; - - handleSystemDeleteConfirm = () => { - this.setState({ openSystemDeleteConfirm: false }); - this.props.systemActions - .deleteSystem(this.props.system.shortName) - .then(requestMessage => { - if (requestMessage) { - // report to the user is there was a problem during login - this.setState({ requestMessage: requestMessage, openMessage: true }); - } - }); - }; - handleSystemDeleteCancel = () => - this.setState({ openSystemDeleteConfirm: false }); - handlePermissionDeleteCancel = () => - this.setState({ openPermissionDeleteConfirm: false }); - render() { - const system = this.props.system; - let fileInput = null; - var location = ""; - var example = ""; - var groupRender = () => {}; - - if (system) { - if (this.props.talkgroups && this.props.talkgroups.length) { - groupRender = () => ( -
- - - -
- ); - } else { - groupRender = () => ( - - - - ); - } - - - example = - '{\n\t"systems": [\n\t\t{\n\t\t\t"shortName": "' + - system.shortName + - '",\n\t\t\t"apiKey": "' + - system.key + - '"\n\t\t}\n\t],\n\t"uploadServer": "' + - process.env.REACT_APP_BACKEND_SERVER + - '"\n}'; - - 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; - } + if (system) { + if (isTalkgroupsSuccess && talkgroupsData.length) { + groupRender = () => ( +
+ + + +
+ ); + } else { + groupRender = () => ( + + + + ); } - const panes = [ - { - menuItem: "Overview", - render: () => ( -
- - - -
Location
- {location} -
- -
Short Name
- {this.props.system.shortName} -
- -
Description
- {this.props.system.description} -
- -
- ) - }, - { - menuItem: "Config", - render: () => ( -
- -
Configure Trunk Recorder
-

- Below are the parameters you will need to configure Trunk - Recorder. The example below shows how they should be added to - the config.json file. -

+ example = + '{\n\t"systems": [\n\t\t{\n\t\t\t"shortName": "' + + system.shortName + + '",\n\t\t\t"apiKey": "' + + system.key + + '"\n\t\t}\n\t],\n\t"uploadServer": "' + + process.env.REACT_APP_BACKEND_SERVER + + '"\n}'; - - -
API Key
- {this.props.system.key} -
- -
Short Name
- {this.props.system.shortName} -
- -
Upload Server
- {process.env.REACT_APP_BACKEND_SERVER} -
- -
Example
-
-