mirror of
https://github.com/openmhz/trunk-server.git
synced 2026-11-14 01:37:48 -05:00
Gettign going
This commit is contained in:
@@ -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 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 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 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) {
|
module.exports = function(app, passport) {
|
||||||
app.set("port", 3009)
|
app.set("port", 3009)
|
||||||
|
|||||||
@@ -14,10 +14,13 @@ module.exports = function (app, passport) {
|
|||||||
done(null, user.id)
|
done(null, user.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
passport.deserializeUser((id, done) => {
|
passport.deserializeUser(async (id, done) => {
|
||||||
User.findById(id, (err, user) => {
|
const user = await User.findById(id).exec();
|
||||||
done(err, user)
|
if (user) {
|
||||||
})
|
done(null,user);
|
||||||
|
} else {
|
||||||
|
done("User not found", null);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// use the following strategies
|
// use the following strategies
|
||||||
|
|||||||
@@ -5,58 +5,52 @@ const System = require("../models/system");
|
|||||||
|
|
||||||
// -------------------------------------------
|
// -------------------------------------------
|
||||||
|
|
||||||
exports.getUserSystems = function(_id) {
|
exports.getUserSystems = async function (_id) {
|
||||||
console.log("Listing Systems for: " + _id);
|
console.log("Listing Systems for: " + _id);
|
||||||
System.find(
|
const userId = new mongoose.Types.ObjectId(req.user._id);
|
||||||
{
|
const systems = await System.find({ userId: userId });
|
||||||
userId: mongoose.Types.ObjectId(_id)
|
if (systems == null) {
|
||||||
},
|
return ({ success: false, message: err });
|
||||||
function(err, systems) {
|
}
|
||||||
if (err) {
|
|
||||||
console.error("Error - ListSystems: " + err);
|
var returnSys = systems.map(obj => {
|
||||||
return({ success: false, message: err });
|
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;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
var returnSys = systems.map(obj => {
|
return ({ success: true, systems: returnSys });
|
||||||
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# build environment
|
# build environment
|
||||||
FROM node:13.12.0-alpine as build
|
FROM node:19-alpine3.16 as build
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ENV PATH /app/node_modules/.bin:$PATH
|
ENV PATH /app/node_modules/.bin:$PATH
|
||||||
ARG REACT_APP_BACKEND_SERVER
|
ARG REACT_APP_BACKEND_SERVER
|
||||||
@@ -15,7 +15,7 @@ COPY . ./
|
|||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
# production environment
|
# production environment
|
||||||
FROM node:13.12.0-alpine
|
FROM node:19-alpine3.16
|
||||||
RUN mkdir -p /app/public
|
RUN mkdir -p /app/public
|
||||||
COPY ./package.json /tmp
|
COPY ./package.json /tmp
|
||||||
RUN cd /tmp && npm install
|
RUN cd /tmp && npm install
|
||||||
|
|||||||
@@ -3,41 +3,42 @@
|
|||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@visx/axis": "1.4.0",
|
"@lagunovsky/redux-react-router": "^4.3.0",
|
||||||
"@visx/curve": "1.0.0",
|
"@visx/axis": "3.0.1",
|
||||||
"@visx/glyph": "1.0.0",
|
"@visx/curve": "3.0.0",
|
||||||
"@visx/group": "1.0.0",
|
"@visx/glyph": "3.0.0",
|
||||||
"@visx/legend": "1.4.0",
|
"@visx/group": "3.0.0",
|
||||||
"@visx/responsive": "1.3.0",
|
"@visx/legend": "3.0.0",
|
||||||
"@visx/scale": "1.4.0",
|
"@visx/responsive": "3.0.0",
|
||||||
"@visx/shape": "1.4.0",
|
"@visx/scale": "3.0.0",
|
||||||
"bcrypt": "5.0.0",
|
"@visx/shape": "3.0.0",
|
||||||
|
"bcrypt": "5.1.0",
|
||||||
"bcryptjs": "2.4.3",
|
"bcryptjs": "2.4.3",
|
||||||
"connect-mongo": "3.2.0",
|
"connect-mongo": "^4.6.0",
|
||||||
"csv-parse": "4.14.2",
|
"csv-parse": "5.3.6",
|
||||||
"d3-time-format": "3.0.0",
|
"d3-time-format": "4.1.0",
|
||||||
"express": "4.17.1",
|
"express": "4.18.2",
|
||||||
"express-session": "1.17.1",
|
"express-session": "1.17.3",
|
||||||
"mongoose": "5.11.11",
|
"history": "^5.3.0",
|
||||||
"multer": "1.4.2",
|
"mongoose": "7.0.0",
|
||||||
"passport": "0.4.1",
|
"multer": "1.4.5-lts.1",
|
||||||
|
"passport": "0.6.0",
|
||||||
"passport-local": "1.0.0"
|
"passport-local": "1.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@reduxjs/toolkit": "^1.1.0",
|
"@reduxjs/toolkit": "^1.9.3",
|
||||||
"@testing-library/jest-dom": "^4.2.4",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@testing-library/react": "^9.3.2",
|
"@testing-library/react": "^14.0.0",
|
||||||
"@testing-library/user-event": "^7.1.2",
|
"@testing-library/user-event": "^14.4.3",
|
||||||
"axios": "0.21.1",
|
"axios": "1.3.4",
|
||||||
"connected-react-router": "6.8.0",
|
"react": "^18.2.0",
|
||||||
"react": "^17.0.1",
|
"react-dom": "^18.2.0",
|
||||||
"react-dom": "^17.0.1",
|
"react-redux": "^8.0.5",
|
||||||
"react-redux": "^7.1.3",
|
"react-router-dom": "6.8.2",
|
||||||
"react-router-dom": "5.2.0",
|
"react-scripts": "5.0.1",
|
||||||
"react-scripts": "4.0.1",
|
"redux-thunk": "2.4.2",
|
||||||
"redux-thunk": "2.3.0",
|
"semantic-ui-css": "2.5.0",
|
||||||
"semantic-ui-css": "2.4.1",
|
"semantic-ui-react": "2.1.4"
|
||||||
"semantic-ui-react": "2.0.1"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "react-scripts start",
|
||||||
|
|||||||
@@ -2,16 +2,15 @@ const path = require("path");
|
|||||||
const express = require("express");
|
const express = require("express");
|
||||||
const session = require("express-session");
|
const session = require("express-session");
|
||||||
const bodyParser = require("body-parser");
|
const bodyParser = require("body-parser");
|
||||||
const connectMongo = require("connect-mongo");
|
const MongoStore = require("connect-mongo");
|
||||||
const secrets = require("./secrets");
|
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 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 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 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 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 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) {
|
module.exports = function(app, passport) {
|
||||||
app.set("port", 3008)
|
app.set("port", 3008)
|
||||||
@@ -36,9 +35,12 @@ module.exports = function(app, passport) {
|
|||||||
secure: false,
|
secure: false,
|
||||||
domain: cookie_domain
|
domain: cookie_domain
|
||||||
},
|
},
|
||||||
store: new MongoStore({
|
store: MongoStore.create({
|
||||||
url: secrets.db,
|
mongoUrl: secrets.db,
|
||||||
autoReconnect: true
|
autoReconnect: true,
|
||||||
|
autoRemove: 'interval',
|
||||||
|
autoRemoveInterval: 240,
|
||||||
|
touchAfter: 24 * 3600 // time period in seconds
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,10 +14,13 @@ module.exports = function (app, passport) {
|
|||||||
done(null, user.id)
|
done(null, user.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
passport.deserializeUser((id, done) => {
|
passport.deserializeUser(async (id, done) => {
|
||||||
User.findById(id, (err, user) => {
|
const user = await User.findById(id).exec();
|
||||||
done(err, user)
|
if (user) {
|
||||||
})
|
done(null,user);
|
||||||
|
} else {
|
||||||
|
done("User not found", null);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,286 +4,241 @@ const mongoose = require("mongoose");
|
|||||||
|
|
||||||
//router.get('/system/:shortName/group/:groupId?', isLoggedIn, function(req, res) {
|
//router.get('/system/:shortName/group/:groupId?', isLoggedIn, function(req, res) {
|
||||||
|
|
||||||
exports.getGroups = function(req, res, next) {
|
exports.getGroups = async function (req, res, next) {
|
||||||
process.nextTick(function() {
|
process.nextTick(async function () {
|
||||||
System.findOne(
|
const system = await System.findOne({ shortName: req.params.shortName.toLowerCase() });
|
||||||
{
|
if (!system) {
|
||||||
shortName: req.params.shortName.toLowerCase()
|
res.status(404);
|
||||||
},
|
res.json({ success: false });
|
||||||
function(err, system) {
|
return;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req.params.groupId) {
|
if (!system.userId.equals(req.user._id)) {
|
||||||
var groupId = req.params.groupId.toLowerCase();
|
res.status(401)
|
||||||
|
res.json({
|
||||||
|
success: false,
|
||||||
|
message: "You are not the user associated with this system."
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Group.findOne(
|
if (req.params.groupId) {
|
||||||
{
|
var groupId = req.params.groupId.toLowerCase();
|
||||||
_id: new mongoose.Types.ObjectId(groupId),
|
|
||||||
shortName: req.params.shortName.toLowerCase()
|
const group = await Group.findOne(
|
||||||
},
|
{
|
||||||
{ sort: { position: -1 } },
|
_id: new mongoose.Types.ObjectId(groupId),
|
||||||
function(err, group) {
|
shortName: req.params.shortName.toLowerCase()
|
||||||
if (err) {
|
},
|
||||||
res.json({
|
{ sort: { position: -1 } });
|
||||||
success: false,
|
if (!group) {
|
||||||
message: err
|
res.status(404);
|
||||||
});
|
res.json({ success: false });
|
||||||
return;
|
return;
|
||||||
} else {
|
|
||||||
res.json({
|
} else {
|
||||||
success: true,
|
res.json(group);
|
||||||
group: group
|
return;
|
||||||
});
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
);
|
} 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) {
|
exports.deleteGroup = function (req, res, next) {
|
||||||
//router.get('/system/:shortName/remove_group/:groupId', isLoggedIn, function(req, res) {
|
//router.get('/system/:shortName/remove_group/:groupId', isLoggedIn, function(req, res) {
|
||||||
System.findOne({
|
System.findOne({
|
||||||
'shortName': req.params.shortName.toLowerCase()
|
'shortName': req.params.shortName.toLowerCase()
|
||||||
}, function(err, system) {
|
}, 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) {
|
if (err) {
|
||||||
console.error(err);
|
|
||||||
res.json({ success: false, message: err });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!system) {
|
|
||||||
console.error(err);
|
|
||||||
res.json({
|
res.json({
|
||||||
success: false,
|
success: false,
|
||||||
message: "That Short Name does not exist."
|
message: err
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
res.json({
|
res.json({
|
||||||
success: true
|
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) {
|
//router.post('/system/:shortName/group/:groupId?', isLoggedIn, function(req, res) {
|
||||||
process.nextTick(function() {
|
process.nextTick(async function () {
|
||||||
System.findOne(
|
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()
|
shortName: req.params.shortName.toLowerCase()
|
||||||
},
|
},
|
||||||
function(err, system) {
|
{
|
||||||
if (err) {
|
groupName: groupName,
|
||||||
console.error(err);
|
talkgroups: talkgroups
|
||||||
res.json({ success: false, message: err });
|
},
|
||||||
return;
|
{
|
||||||
}
|
new: true,
|
||||||
if (!system) {
|
upsert: true
|
||||||
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);
|
|
||||||
|
|
||||||
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) {
|
if (!group) {
|
||||||
res.json({
|
res.status(500);
|
||||||
success: false,
|
res.json({
|
||||||
message: message
|
success: false,
|
||||||
});
|
message: err
|
||||||
return;
|
});
|
||||||
}
|
return;
|
||||||
// if we got here, that means that everything is good for updating/inserting
|
} else {
|
||||||
|
res.json(group);
|
||||||
var groupId = req.params.groupId;
|
return;
|
||||||
|
}
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -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);
|
console.log("Listing Systems for: " + req.user._id);
|
||||||
System.find({
|
const userId = new mongoose.Types.ObjectId(req.user._id);
|
||||||
userId: mongoose.Types.ObjectId(req.user._id)
|
const systems = await System.find({ userId: userId }).exec();
|
||||||
},
|
if (systems == null) {
|
||||||
function (err, systems) {
|
res.status(400);
|
||||||
if (err) {
|
res.json({ success: false, message: err });
|
||||||
console.error("Error - ListSystems: " + err);
|
return;
|
||||||
res.json({
|
}
|
||||||
success: false,
|
|
||||||
message: err
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var shortNames = new Array();
|
let shortNames = new Array();
|
||||||
for (var i = 0; i < systems.length; i++) {
|
for (var i = 0; i < systems.length; i++) {
|
||||||
shortNames.push(systems[i].shortName);
|
shortNames.push(systems[i].shortName);
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemStat.find({
|
const stats = await SystemStat.find({ shortName: { $in: shortNames } }).exec();
|
||||||
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] = {};
|
|
||||||
|
|
||||||
sys_stats[stats[i].shortName].callTotals = stats[i].callTotals;
|
let returnSys = systems.map(obj => {
|
||||||
sys_stats[stats[i].shortName].errorTotals = stats[i].errorTotals;
|
var rObj = (({
|
||||||
sys_stats[stats[i].shortName].errorStats = stats[i].errorStats;
|
name,
|
||||||
sys_stats[stats[i].shortName].usageBytes = stats[i].usageBytes;
|
shortName,
|
||||||
sys_stats[stats[i].shortName].usageMb = stats[i].usageMb;
|
description,
|
||||||
}
|
systemType,
|
||||||
|
city,
|
||||||
res.json({
|
state,
|
||||||
success: true,
|
county,
|
||||||
systems: returnSys,
|
country,
|
||||||
stats: sys_stats
|
userId,
|
||||||
});
|
key,
|
||||||
return;
|
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) {
|
function remove_system(shortName) {
|
||||||
@@ -115,8 +100,8 @@ function remove_system(shortName) {
|
|||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
System.remove({
|
System.remove({
|
||||||
shortName: shortName
|
shortName: shortName
|
||||||
},
|
},
|
||||||
function (err) {
|
function (err) {
|
||||||
if (err) return console.error(err);
|
if (err) return console.error(err);
|
||||||
// removed!
|
// removed!
|
||||||
@@ -124,8 +109,8 @@ function remove_system(shortName) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
Talkgroup.remove({
|
Talkgroup.remove({
|
||||||
shortName: shortName
|
shortName: shortName
|
||||||
},
|
},
|
||||||
function (err) {
|
function (err) {
|
||||||
if (err) return console.error(err);
|
if (err) return console.error(err);
|
||||||
// removed!
|
// removed!
|
||||||
@@ -133,8 +118,8 @@ function remove_system(shortName) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
Group.remove({
|
Group.remove({
|
||||||
shortName: shortName
|
shortName: shortName
|
||||||
},
|
},
|
||||||
function (err) {
|
function (err) {
|
||||||
if (err) return console.error(err);
|
if (err) return console.error(err);
|
||||||
// removed!
|
// removed!
|
||||||
@@ -145,8 +130,8 @@ function remove_system(shortName) {
|
|||||||
exports.deleteSystem = function (req, res, next) {
|
exports.deleteSystem = function (req, res, next) {
|
||||||
//router.get('/delete_system/:shortName', isLoggedIn, function(req, res) {
|
//router.get('/delete_system/:shortName', isLoggedIn, function(req, res) {
|
||||||
System.findOne({
|
System.findOne({
|
||||||
shortName: req.params.shortName.toLowerCase()
|
shortName: req.params.shortName.toLowerCase()
|
||||||
},
|
},
|
||||||
function (err, system) {
|
function (err, system) {
|
||||||
if (err) {
|
if (err) {
|
||||||
res.json({
|
res.json({
|
||||||
@@ -224,7 +209,7 @@ exports.uniqueShortName = async function (req, res, next) {
|
|||||||
|
|
||||||
var shortName = res.locals.shortName;
|
var shortName = res.locals.shortName;
|
||||||
if (typeof shortName == 'undefined') {
|
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")
|
console.error("ShortName is not in res.local, pulling from req.body instead")
|
||||||
shortName = req.body.shortName;
|
shortName = req.body.shortName;
|
||||||
}
|
}
|
||||||
@@ -329,7 +314,7 @@ exports.updateSystem = async function (req, res, next) {
|
|||||||
exports.validateSystem = async function (req, res, next) {
|
exports.validateSystem = async function (req, res, next) {
|
||||||
try {
|
try {
|
||||||
res.locals.showScreenName = req.body.showScreenName;
|
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)) {
|
if (!req.body.name || (req.body.name.length < 2)) {
|
||||||
console.error("ERROR: Validate System - req.body.name");
|
console.error("ERROR: Validate System - req.body.name");
|
||||||
res.json({
|
res.json({
|
||||||
@@ -471,7 +456,7 @@ exports.createSystem = async function (req, res, next) {
|
|||||||
ignoreUnknownTalkgroup
|
ignoreUnknownTalkgroup
|
||||||
}))(res.locals);
|
}))(res.locals);
|
||||||
system.key = key;
|
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) {
|
System.create(system, function (err, newSys) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@@ -492,7 +477,7 @@ exports.createSystem = async function (req, res, next) {
|
|||||||
country,
|
country,
|
||||||
userId,
|
userId,
|
||||||
showScreenName,
|
showScreenName,
|
||||||
ignoreUnknownTalkgroup ,
|
ignoreUnknownTalkgroup,
|
||||||
key
|
key
|
||||||
}) => ({
|
}) => ({
|
||||||
name,
|
name,
|
||||||
@@ -505,7 +490,7 @@ exports.createSystem = async function (req, res, next) {
|
|||||||
country,
|
country,
|
||||||
userId,
|
userId,
|
||||||
showScreenName,
|
showScreenName,
|
||||||
ignoreUnknownTalkgroup ,
|
ignoreUnknownTalkgroup,
|
||||||
key
|
key
|
||||||
}))(newSys);
|
}))(newSys);
|
||||||
returnSys.id = newSys._id;
|
returnSys.id = newSys._id;
|
||||||
|
|||||||
@@ -5,251 +5,217 @@ const fs = require('fs-extra');
|
|||||||
const crypto = require("crypto");
|
const crypto = require("crypto");
|
||||||
var parse = require('csv-parse');
|
var parse = require('csv-parse');
|
||||||
|
|
||||||
exports.isLoggedIn = function(req, res, next) {
|
exports.isLoggedIn = function (req, res, next) {
|
||||||
if (req.isAuthenticated()) return next();
|
if (req.isAuthenticated()) return next();
|
||||||
res.redirect(account_server + "/login");
|
res.redirect(account_server + "/login");
|
||||||
};
|
};
|
||||||
|
|
||||||
//router.get("/tg_export/:shortName", isLoggedIn, function(req, res) {
|
//router.get("/tg_export/:shortName", isLoggedIn, function(req, res) {
|
||||||
exports.exportTalkgroups = function(req, res, next) {
|
exports.exportTalkgroups = function (req, res, next) {
|
||||||
process.nextTick(function() {
|
process.nextTick(async function () {
|
||||||
System.findOne(
|
const system = await System.findOne({ shortName: req.params.shortName.toLowerCase() });
|
||||||
{
|
if (!system) {
|
||||||
shortName: req.params.shortName.toLowerCase()
|
res.status(404);
|
||||||
},
|
res.json({
|
||||||
function(err, system) {
|
success: false,
|
||||||
if (err) {
|
message: "That Short Name does not exist."
|
||||||
console.error(err);
|
});
|
||||||
res.json({ success: false, message: err });
|
return;
|
||||||
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!
|
|
||||||
}
|
}
|
||||||
|
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) {
|
async function csv_import(shortName, filename, callback) {
|
||||||
exports.importTalkgroups = function(req, res, next) {
|
var talkgroups = [];
|
||||||
process.nextTick(function() {
|
const count = await Talkgroup.deleteMany({ shortName: shortName });
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.exists(req.file.path, function(exists) {
|
var parser = parse(
|
||||||
if (exists) {
|
{
|
||||||
csv_import(system.shortName, req.file.path, function(err, data) {
|
columns: [
|
||||||
if (err) {
|
"num",
|
||||||
console.error("Erorr - CSV import, callback: " + err);
|
"mode",
|
||||||
res.json({ success: false, message: err });
|
"alpha",
|
||||||
res.end();
|
"description",
|
||||||
return;
|
"tag",
|
||||||
} else {
|
"group",
|
||||||
res.json({ success: true, talkgroups: data });
|
"priority"
|
||||||
return;
|
]
|
||||||
}
|
},
|
||||||
});
|
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 {
|
} else {
|
||||||
console.error("Error - importTalkgroups: no file");
|
res.json( data );
|
||||||
res.end(
|
return;
|
||||||
"Well, there is no magic for those who don’t believe in it!"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} 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) {
|
exports.fetchTalkgroups = async function (req, res, next) {
|
||||||
Talkgroup.find(
|
const talkgroups = await Talkgroup.find({ shortName: req.params.shortName.toLowerCase() }).catch(err => {
|
||||||
{
|
console.error(err);
|
||||||
shortName: req.params.shortName.toLowerCase()
|
res.status(500);
|
||||||
},
|
res.json({ success: false, message: err });
|
||||||
function(err, talkgroups) {
|
return;
|
||||||
if (err) {
|
});
|
||||||
console.error(err);
|
|
||||||
res.json({ success: false, message: err });
|
res.json(talkgroups );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
res.json({ success: true, talkgroups: talkgroups });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -42,13 +42,7 @@ async function connect() {
|
|||||||
|
|
||||||
// Connect to a MongoDB server running on 'localhost:27017' and use the
|
// Connect to a MongoDB server running on 'localhost:27017' and use the
|
||||||
// 'test' database.
|
// 'test' database.
|
||||||
await mongoose.connect(secrets.db, { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true }, (err, res) => {
|
await mongoose.connect(secrets.db, { useNewUrlParser: true, useUnifiedTopology: true });
|
||||||
if (err) {
|
|
||||||
console.log(`Mongoose - Error connecting to ${secrets.db}. ${err}`)
|
|
||||||
} else {
|
|
||||||
console.log(`Mongoose Successfully connected to ${secrets.db}.`)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
console.log("All Done");
|
console.log("All Done");
|
||||||
}
|
}
|
||||||
connect();
|
connect();
|
||||||
|
|||||||
@@ -1,15 +1,48 @@
|
|||||||
import React, { Component } from "react"
|
import React, { Component } from "react"
|
||||||
import NavigationContainer from "./NavigationContainer"
|
import NavigationContainer from "./NavigationContainer"
|
||||||
|
import { Routes, Route } from 'react-router-dom';
|
||||||
|
|
||||||
class App extends Component {
|
import Restricted from "./Restricted"
|
||||||
render() {
|
|
||||||
return(
|
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 (
|
||||||
<div>
|
<div>
|
||||||
<NavigationContainer />
|
<NavigationContainer />
|
||||||
{this.props.children}
|
<Routes>
|
||||||
|
<Route path="/about" element={ <Restricted><About/></Restricted>} />
|
||||||
|
<Route path="/system/:shortName" element={ <Restricted><System/></Restricted>} />
|
||||||
|
<Route path="/update-system/:shortName" component={Restricted(UpdateSystemContainer, store)} />
|
||||||
|
<Route path="/create-system" component={Restricted(CreateSystemContainer, store)} />
|
||||||
|
<Route path="/list-systems" element={ <Restricted><ListSystems/></Restricted>} />
|
||||||
|
<Route path="/" element={ <Restricted><ListSystems/></Restricted>} />
|
||||||
|
<Route render={() => (<div>Miss</div>)} />
|
||||||
|
</Routes>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
/*
|
||||||
}
|
return (
|
||||||
|
<div>
|
||||||
|
<NavigationContainer />
|
||||||
|
<Routes>
|
||||||
|
<Route path="/about" element={<About />} component={Restricted(About, store)} />
|
||||||
|
<Route path="/system/:shortName" component={Restricted(SystemContainer, store)} />
|
||||||
|
<Route path="/update-system/:shortName" component={Restricted(UpdateSystemContainer, store)} />
|
||||||
|
<Route path="/create-system" component={Restricted(CreateSystemContainer, store)} />
|
||||||
|
<Route path="/list-systems" component={Restricted(ListSystemsContainer, store)} />
|
||||||
|
<Route path="/" component={Restricted(ListSystemsContainer, store)} />
|
||||||
|
<Route render={() => (<div>Miss</div>)} />
|
||||||
|
</Routes>
|
||||||
|
</div>
|
||||||
|
)*/
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
export default App
|
export default App
|
||||||
|
|||||||
@@ -1,12 +1,46 @@
|
|||||||
// in src/restricted.js
|
// in src/restricted.js
|
||||||
import React, { Component } from 'react';
|
//import React, { Component } from 'react';
|
||||||
import { withRouter } from 'react-router-dom';
|
import React, { useEffect, useLayoutEffect, useState, useRef, useCallback, useMemo } from "react";
|
||||||
|
import { useSelector, useDispatch } from 'react-redux'
|
||||||
import * as types from "../User/user-constants";
|
import * as types from "../User/user-constants";
|
||||||
import axios from "axios";
|
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
|
* 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 <div/>
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
const restricted = (BaseComponent, store) => {
|
const restricted = (BaseComponent, store) => {
|
||||||
|
|
||||||
class Restricted extends Component {
|
class Restricted extends Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.checkAuthentication(this.props);
|
this.checkAuthentication(this.props);
|
||||||
@@ -32,8 +66,6 @@ const restricted = (BaseComponent, store) => {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
window.location = process.env.REACT_APP_ACCOUNT_SERVER + "/login?nextLocation=admin";
|
window.location = process.env.REACT_APP_ACCOUNT_SERVER + "/login?nextLocation=admin";
|
||||||
/*history.replace({ pathname: '/login',
|
|
||||||
state: { nextPathname: params.location.pathname } });*/
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(response => {
|
.catch(response => {
|
||||||
@@ -51,4 +83,6 @@ const restricted = (BaseComponent, store) => {
|
|||||||
}
|
}
|
||||||
return withRouter(Restricted);
|
return withRouter(Restricted);
|
||||||
}
|
}
|
||||||
export default restricted
|
*/
|
||||||
|
|
||||||
|
export default Restricted
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import { Container, Header } from "semantic-ui-react";
|
import { Container, Header } from "semantic-ui-react";
|
||||||
|
|
||||||
class About extends Component {
|
const About = () => {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
return (
|
||||||
<Container text>
|
<Container text>
|
||||||
<Header size='large'>Share the Air</Header>
|
<Header size='large'>Share the Air</Header>
|
||||||
@@ -18,7 +18,7 @@ class About extends Component {
|
|||||||
<p> - Luke <a href="mailto:{process.env.REACT_APP_ADMIN_EMAIL}?Subject={process.env.REACT_APP_SITE_NAME}" target="_top">{process.env.REACT_APP_ADMIN_EMAIL}</a> </p>
|
<p> - Luke <a href="mailto:{process.env.REACT_APP_ADMIN_EMAIL}?Subject={process.env.REACT_APP_SITE_NAME}" target="_top">{process.env.REACT_APP_ADMIN_EMAIL}</a> </p>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default About;
|
export default About;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
//import { browserHistory } from "react-router"
|
//import { browserHistory } from "react-router"
|
||||||
import * as types from "./group-constants";
|
import * as types from "./group-constants";
|
||||||
import { push } from 'connected-react-router';
|
import { push } from '@lagunovsky/redux-react-router'
|
||||||
|
|
||||||
// "Log In" action creators
|
// "Log In" action creators
|
||||||
function beginCreateGroup() {
|
function beginCreateGroup() {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { Component } from "react";
|
import { Component, useRef } from "react";
|
||||||
import SystemCard from "./SystemCard";
|
import SystemCard from "./SystemCard";
|
||||||
import {
|
import {
|
||||||
Container,
|
Container,
|
||||||
@@ -8,37 +8,40 @@ import {
|
|||||||
Icon,
|
Icon,
|
||||||
Button,
|
Button,
|
||||||
} from "semantic-ui-react";
|
} 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 {
|
const ListSystems = (props) => {
|
||||||
|
const { data, isSuccess } = useGetSystemsQuery();
|
||||||
state = {
|
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/36559661/how-can-i-dispatch-from-child-components-in-react-redux
|
||||||
//https://stackoverflow.com/questions/42597602/react-onclick-pass-event-with-parameter
|
//https://stackoverflow.com/questions/42597602/react-onclick-pass-event-with-parameter
|
||||||
render() {
|
|
||||||
const systems = this.props.system.items;
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Container>
|
<Container>
|
||||||
<Header as="h1">Radio Systems</Header>
|
<Header as="h1">Radio Systems</Header>
|
||||||
<Button onClick={(e) => this.props.changeUrl("/create-system")}><Icon name='plus' />Add System</Button>
|
<Button onClick={(e) => dispatch(push("/create-system"))}><Icon name='plus' />Add System</Button>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Card.Group itemsPerRow={4}>
|
<Card.Group itemsPerRow={4}>
|
||||||
{systems.map((system) =>
|
{systems &&
|
||||||
<SystemCard system={system} key={system.shortName} onClick={(e) => this.props.changeUrl("/system/" + system.shortName)}/>
|
systems.map((system) =>
|
||||||
|
<SystemCard system={system} key={system.shortName} onClick={(e) => dispatch(push("/system/" + system.shortName))}/>
|
||||||
)}
|
)}
|
||||||
</Card.Group>
|
</Card.Group>
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ListSystems;
|
export default ListSystems;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -9,11 +9,9 @@ import {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SystemCard extends Component {
|
const SystemCard = (props) => {
|
||||||
|
|
||||||
render() {
|
|
||||||
var location = "";
|
var location = "";
|
||||||
const system = this.props.system;
|
const { system } = props;
|
||||||
|
|
||||||
|
|
||||||
if (system) {
|
if (system) {
|
||||||
@@ -37,26 +35,26 @@ render() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Card link onClick={this.props.onClick}>
|
<Card link onClick={props.onClick}>
|
||||||
|
|
||||||
<Card.Content>
|
<Card.Content>
|
||||||
<Header size='medium'>
|
<Header size='medium'>
|
||||||
<Header.Content>
|
<Header.Content>
|
||||||
{system.name}
|
{system.name}
|
||||||
<Header.Subheader>{system.screenName}</Header.Subheader>
|
<Header.Subheader>{system.screenName}</Header.Subheader>
|
||||||
</Header.Content>
|
</Header.Content>
|
||||||
</Header>
|
</Header>
|
||||||
</Card.Content><Card.Content>
|
</Card.Content><Card.Content>
|
||||||
|
|
||||||
<Card.Description>{system.description}</Card.Description>
|
<Card.Description>{system.description}</Card.Description>
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
<Card.Content extra>
|
<Card.Content extra>
|
||||||
<Icon name='marker' />
|
<Icon name='marker' />
|
||||||
{location}
|
{location}
|
||||||
</Card.Content>
|
</Card.Content>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SystemCard;
|
export default SystemCard;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
//import { browserHistory } from "react-router"
|
//import { browserHistory } from "react-router"
|
||||||
import * as types from "./error-constants";
|
import * as types from "./error-constants";
|
||||||
import { push } from 'connected-react-router';
|
import { push } from '@lagunovsky/redux-react-router';
|
||||||
|
|
||||||
|
|
||||||
function beginFetch() {
|
function beginFetch() {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
//import { browserHistory } from "react-router"
|
//import { browserHistory } from "react-router"
|
||||||
import * as types from "./system-constants";
|
import * as types from "./system-constants";
|
||||||
import { push } from 'connected-react-router';
|
import { push } from '@lagunovsky/redux-react-router';
|
||||||
|
|
||||||
|
|
||||||
// "Log In" action creators
|
// "Log In" action creators
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import axios, { post } from 'axios';
|
import axios from 'axios';
|
||||||
//import { browserHistory } from "react-router"
|
//import { browserHistory } from "react-router"
|
||||||
import * as types from "./talkgroup-constants";
|
import * as types from "./talkgroup-constants";
|
||||||
import { push } from 'connected-react-router';
|
import { push } from '@lagunovsky/redux-react-router';
|
||||||
|
|
||||||
// "Log In" action creators
|
// "Log In" action creators
|
||||||
function beginImportTalkgroup() {
|
function beginImportTalkgroup() {
|
||||||
@@ -58,7 +58,7 @@ function fileUpload(shortName, file){
|
|||||||
},
|
},
|
||||||
withCredentials: true
|
withCredentials: true
|
||||||
}
|
}
|
||||||
return post(url, formData,config)
|
return axios.post(url, formData,config)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example of an Async Action Creator
|
// Example of an Async Action Creator
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
//import { browserHistory } from "react-router"
|
//import { browserHistory } from "react-router"
|
||||||
import * as types from "./user-constants";
|
import * as types from "./user-constants";
|
||||||
import { push } from 'connected-react-router';
|
import { push } from '@lagunovsky/redux-react-router';
|
||||||
|
|
||||||
|
|
||||||
// "Log Out" action creators
|
// "Log Out" action creators
|
||||||
|
|||||||
73
admin/src/features/api/apiSlice.js
Normal file
73
admin/src/features/api/apiSlice.js
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
// Import the RTK Query methods from the React-specific entry point
|
||||||
|
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
|
||||||
|
import { createSelector} from '@reduxjs/toolkit'
|
||||||
|
|
||||||
|
|
||||||
|
// Define our single API slice object
|
||||||
|
export const apiSlice = createApi({
|
||||||
|
// The cache reducer expects to be added at `state.api` (already default - this is optional)
|
||||||
|
reducerPath: 'api',
|
||||||
|
// All of our requests will have URLs starting with '/fakeApi'
|
||||||
|
baseQuery: fetchBaseQuery({ baseUrl: process.env.REACT_APP_ADMIN_SERVER}),
|
||||||
|
// The "endpoints" represent operations and requests for this server
|
||||||
|
endpoints: builder => ({
|
||||||
|
// The `getPosts` endpoint is a "query" operation that returns data
|
||||||
|
getTalkgroups: builder.query({
|
||||||
|
// The URL for the request is '/fakeApi/posts'
|
||||||
|
query: (shortName) => ({ url: `/talkgroups/${shortName}`, credentials: "include" })
|
||||||
|
}),
|
||||||
|
getGroups: builder.query({
|
||||||
|
// The URL for the request is '/fakeApi/posts'
|
||||||
|
query: (shortName) => ({ url: `/groups/${shortName}`, credentials: "include" })
|
||||||
|
}),
|
||||||
|
getErrors: builder.query({
|
||||||
|
// The URL for the request is '/fakeApi/posts'
|
||||||
|
query: (shortName) => ({ url: `${process.env.REACT_APP_BACKEND_SERVER}/${shortName}/errors`})
|
||||||
|
}),
|
||||||
|
updateGroup: builder.mutation({
|
||||||
|
query: (group) => ({
|
||||||
|
url: `/groups/${group.shortName}/${group._id}`,
|
||||||
|
method: 'POST',
|
||||||
|
credentials: "include",
|
||||||
|
body: group,
|
||||||
|
}),
|
||||||
|
async onQueryStarted(group, { dispatch, queryFulfilled }) {
|
||||||
|
try {
|
||||||
|
const { data: updatedGroup } = await queryFulfilled
|
||||||
|
const patchResult = dispatch(
|
||||||
|
apiSlice.util.updateQueryData('getGroups', updatedGroup.shortName, (groups) => {
|
||||||
|
const groupIndex = groups.findIndex((obj => obj.groupId == updatedGroup.groupId));
|
||||||
|
groups[groupIndex] = updatedGroup;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
} catch {}
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
createGroup: builder.mutation({
|
||||||
|
query: (group) => ({
|
||||||
|
url: `/groups/${group.shortName}`,
|
||||||
|
method: 'POST',
|
||||||
|
credentials: "include",
|
||||||
|
body: group,
|
||||||
|
}),
|
||||||
|
async onQueryStarted(group, { dispatch, queryFulfilled }) {
|
||||||
|
try {
|
||||||
|
const { data: newGroup } = await queryFulfilled;
|
||||||
|
const patchResult = dispatch(
|
||||||
|
apiSlice.util.updateQueryData('getGroups', newGroup.shortName, (groups) => {
|
||||||
|
groups.push(newGroup);
|
||||||
|
})
|
||||||
|
)
|
||||||
|
} catch {}
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
getSystems: builder.query({
|
||||||
|
// The URL for the request is '/fakeApi/posts'
|
||||||
|
query: () => ({ url: `/systems`, credentials: "include" })
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Export the auto-generated hook for the `getPosts` query endpoint
|
||||||
|
export const { useGetGroupsQuery, useGetSystemsQuery, useGetTalkgroupsQuery, useGetErrorsQuery} = apiSlice
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
|
||||||
import {
|
|
||||||
decrement,
|
|
||||||
increment,
|
|
||||||
incrementByAmount,
|
|
||||||
incrementAsync,
|
|
||||||
selectCount,
|
|
||||||
} from './counterSlice';
|
|
||||||
import styles from './Counter.module.css';
|
|
||||||
|
|
||||||
export function Counter() {
|
|
||||||
const count = useSelector(selectCount);
|
|
||||||
const dispatch = useDispatch();
|
|
||||||
const [incrementAmount, setIncrementAmount] = useState('2');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<div className={styles.row}>
|
|
||||||
<button
|
|
||||||
className={styles.button}
|
|
||||||
aria-label="Increment value"
|
|
||||||
onClick={() => dispatch(increment())}
|
|
||||||
>
|
|
||||||
+
|
|
||||||
</button>
|
|
||||||
<span className={styles.value}>{count}</span>
|
|
||||||
<button
|
|
||||||
className={styles.button}
|
|
||||||
aria-label="Decrement value"
|
|
||||||
onClick={() => dispatch(decrement())}
|
|
||||||
>
|
|
||||||
-
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div className={styles.row}>
|
|
||||||
<input
|
|
||||||
className={styles.textbox}
|
|
||||||
aria-label="Set increment amount"
|
|
||||||
value={incrementAmount}
|
|
||||||
onChange={e => setIncrementAmount(e.target.value)}
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
className={styles.button}
|
|
||||||
onClick={() =>
|
|
||||||
dispatch(incrementByAmount(Number(incrementAmount) || 0))
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Add Amount
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className={styles.asyncButton}
|
|
||||||
onClick={() => dispatch(incrementAsync(Number(incrementAmount) || 0))}
|
|
||||||
>
|
|
||||||
Add Async
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
.row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.row:not(:last-child) {
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.value {
|
|
||||||
font-size: 78px;
|
|
||||||
padding-left: 16px;
|
|
||||||
padding-right: 16px;
|
|
||||||
margin-top: 2px;
|
|
||||||
font-family: 'Courier New', Courier, monospace;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
|
||||||
appearance: none;
|
|
||||||
background: none;
|
|
||||||
font-size: 32px;
|
|
||||||
padding-left: 12px;
|
|
||||||
padding-right: 12px;
|
|
||||||
outline: none;
|
|
||||||
border: 2px solid transparent;
|
|
||||||
color: rgb(112, 76, 182);
|
|
||||||
padding-bottom: 4px;
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: rgba(112, 76, 182, 0.1);
|
|
||||||
border-radius: 2px;
|
|
||||||
transition: all 0.15s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.textbox {
|
|
||||||
font-size: 32px;
|
|
||||||
padding: 2px;
|
|
||||||
width: 64px;
|
|
||||||
text-align: center;
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button:hover, .button:focus {
|
|
||||||
border: 2px solid rgba(112, 76, 182, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.button:active {
|
|
||||||
background-color: rgba(112, 76, 182, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.asyncButton {
|
|
||||||
composes: button;
|
|
||||||
position: relative;
|
|
||||||
margin-left: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.asyncButton:after {
|
|
||||||
content: "";
|
|
||||||
background-color: rgba(112, 76, 182, 0.15);
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
opacity: 0;
|
|
||||||
transition: width 1s linear, opacity 0.5s ease 1s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.asyncButton:active:after {
|
|
||||||
width: 0%;
|
|
||||||
opacity: 1;
|
|
||||||
transition: 0s
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
import { createSlice } from '@reduxjs/toolkit';
|
|
||||||
|
|
||||||
export const counterSlice = createSlice({
|
|
||||||
name: 'counter',
|
|
||||||
initialState: {
|
|
||||||
value: 0,
|
|
||||||
},
|
|
||||||
reducers: {
|
|
||||||
increment: state => {
|
|
||||||
// Redux Toolkit allows us to write "mutating" logic in reducers. It
|
|
||||||
// doesn't actually mutate the state because it uses the Immer library,
|
|
||||||
// which detects changes to a "draft state" and produces a brand new
|
|
||||||
// immutable state based off those changes
|
|
||||||
state.value += 1;
|
|
||||||
},
|
|
||||||
decrement: state => {
|
|
||||||
state.value -= 1;
|
|
||||||
},
|
|
||||||
incrementByAmount: (state, action) => {
|
|
||||||
state.value += action.payload;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
|
|
||||||
|
|
||||||
// The function below is called a thunk and allows us to perform async logic. It
|
|
||||||
// can be dispatched like a regular action: `dispatch(incrementAsync(10))`. This
|
|
||||||
// will call the thunk with the `dispatch` function as the first argument. Async
|
|
||||||
// code can then be executed and other actions can be dispatched
|
|
||||||
export const incrementAsync = amount => dispatch => {
|
|
||||||
setTimeout(() => {
|
|
||||||
dispatch(incrementByAmount(amount));
|
|
||||||
}, 1000);
|
|
||||||
};
|
|
||||||
|
|
||||||
// The function below is called a selector and allows us to select a value from
|
|
||||||
// the state. Selectors can also be defined inline where they're used instead of
|
|
||||||
// in the slice file. For example: `useSelector((state) => state.counter.value)`
|
|
||||||
export const selectCount = state => state.counter.value;
|
|
||||||
|
|
||||||
export default counterSlice.reducer;
|
|
||||||
15
admin/src/features/group/groupSlice.js
Normal file
15
admin/src/features/group/groupSlice.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
const groupSlice = createSlice({
|
||||||
|
name: 'group',
|
||||||
|
initialState: {
|
||||||
|
orderChange: false,
|
||||||
|
isWaiting: false,
|
||||||
|
items: {}
|
||||||
|
},
|
||||||
|
reducers: {
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// Extract the action creators object and the reducer
|
||||||
|
const { actions, reducer } = groupSlice
|
||||||
|
// Export the reducer, either as a default or named export
|
||||||
|
export default reducer
|
||||||
81
admin/src/features/user/userSlice.js
Normal file
81
admin/src/features/user/userSlice.js
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import {
|
||||||
|
createSlice,
|
||||||
|
createEntityAdapter,
|
||||||
|
createSelector,
|
||||||
|
createAsyncThunk
|
||||||
|
} from '@reduxjs/toolkit'
|
||||||
|
|
||||||
|
|
||||||
|
export const authenticateUser = createAsyncThunk(
|
||||||
|
'user/authenticate',
|
||||||
|
async ({ getState }) => {
|
||||||
|
const url = process.env.REACT_APP_ACCOUNT_SERVER + "/authenticated"
|
||||||
|
const res = await fetch(url, {
|
||||||
|
method: 'GET',
|
||||||
|
credentials: "include"
|
||||||
|
}).then(
|
||||||
|
(data) => data.json()
|
||||||
|
)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
export const logoutUser = createAsyncThunk(
|
||||||
|
'user/logout',
|
||||||
|
async ({ getState }) => {
|
||||||
|
const url = process.env.REACT_APP_ACCOUNT_SERVER + "/logout"
|
||||||
|
const res = await fetch(url, {
|
||||||
|
method: 'GET',
|
||||||
|
credentials: "include"
|
||||||
|
}).then(
|
||||||
|
(data) => data.json()
|
||||||
|
)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
export const userSlice = createSlice({
|
||||||
|
name: 'user',
|
||||||
|
initialState: {
|
||||||
|
isWaiting: false,
|
||||||
|
authenticated: false,
|
||||||
|
hasAuthenticated: false,
|
||||||
|
userId: ""
|
||||||
|
},
|
||||||
|
reducers: {
|
||||||
|
increment: (state) => {
|
||||||
|
// Redux Toolkit allows us to write "mutating" logic in reducers. It
|
||||||
|
// doesn't actually mutate the state because it uses the Immer library,
|
||||||
|
// which detects changes to a "draft state" and produces a brand new
|
||||||
|
// immutable state based off those changes
|
||||||
|
state.value += 1
|
||||||
|
},
|
||||||
|
},
|
||||||
|
extraReducers: {
|
||||||
|
[authenticateUser.fulfilled]: (state, data) => {
|
||||||
|
const {payload} = data;
|
||||||
|
if (payload.success) {
|
||||||
|
state.authenticated = true;
|
||||||
|
state.hasAuthenticated = true;
|
||||||
|
state.userId = payload.user.userId;
|
||||||
|
} else {
|
||||||
|
state.authenticated = false;
|
||||||
|
state.hasAuthenticated = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[authenticateUser.rejected]: (state, { payload }) => {
|
||||||
|
state.authenticated = false;
|
||||||
|
state.hasAuthenticated = true;
|
||||||
|
|
||||||
|
},
|
||||||
|
[logoutUser.fulfilled]: (state, { payload }) => {
|
||||||
|
if (payload.success) {
|
||||||
|
state.authenticated = false;
|
||||||
|
state.userId = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Extract the action creators object and the reducer
|
||||||
|
export const userReducer = userSlice.reducer;
|
||||||
@@ -1,40 +1,23 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
|
||||||
import { Provider } from 'react-redux'
|
import { Provider } from 'react-redux'
|
||||||
import { Route, Switch } from 'react-router' // react-router v4/v5
|
import { createRoot } from 'react-dom/client';
|
||||||
import { ConnectedRouter } from 'connected-react-router'
|
import { BrowserRouter } from "react-router-dom";
|
||||||
import configureStore, { history } from './redux-router/configureStore'
|
import configureStore, { history } from './redux-router/configureStore'
|
||||||
import 'semantic-ui-css/semantic.min.css'
|
import 'semantic-ui-css/semantic.min.css'
|
||||||
import App from "./App/App"
|
import App from "./App/App"
|
||||||
import Restricted from "./App/Restricted"
|
|
||||||
|
|
||||||
import About from "./Components/About"
|
|
||||||
import SystemContainer from "./System/SystemContainer"
|
|
||||||
import ListSystemsContainer from "./System/ListSystemsContainer"
|
|
||||||
import UpdateSystemContainer from "./System/UpdateSystemContainer"
|
|
||||||
import CreateSystemContainer from "./System/CreateSystemContainer"
|
|
||||||
|
|
||||||
const store = configureStore(/* provide initial state if any */)
|
const store = configureStore(/* provide initial state if any */)
|
||||||
|
|
||||||
|
|
||||||
ReactDOM.render(
|
|
||||||
|
const container = document.getElementById('root');
|
||||||
|
const root = createRoot(container);
|
||||||
|
root.render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<ConnectedRouter history={history}> { /* place ConnectedRouter under Provider */ }
|
<BrowserRouter>
|
||||||
<>
|
<App />
|
||||||
<App>
|
</BrowserRouter>
|
||||||
<Switch>
|
</Provider>
|
||||||
<Route path="/about" component={Restricted(About, store)} />
|
|
||||||
<Route path="/system/:shortName" component={Restricted(SystemContainer, store)} />
|
|
||||||
<Route path="/update-system/:shortName" component={Restricted(UpdateSystemContainer, store)} />
|
|
||||||
<Route path="/create-system" component={Restricted(CreateSystemContainer, store)} />
|
|
||||||
<Route path="/list-systems" component={Restricted(ListSystemsContainer,store)} />
|
|
||||||
<Route path="/" component={Restricted(ListSystemsContainer, store)} />
|
|
||||||
<Route render={() => (<div>Miss</div>)} />
|
|
||||||
</Switch>
|
|
||||||
</App>
|
|
||||||
</>
|
|
||||||
</ConnectedRouter>
|
|
||||||
</Provider>,
|
|
||||||
document.getElementById('root')
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,10 @@
|
|||||||
|
|
||||||
import { createBrowserHistory } from 'history'
|
import { createBrowserHistory } from 'history'
|
||||||
import { applyMiddleware, compose, createStore } from 'redux'
|
import { applyMiddleware, compose, createStore } from 'redux'
|
||||||
import { routerMiddleware } from 'connected-react-router'
|
import { createRouterMiddleware } from '@lagunovsky/redux-react-router'
|
||||||
import createRootReducer from './reducers'
|
import createRootReducer from './reducers'
|
||||||
import thunk from 'redux-thunk';
|
import thunk from 'redux-thunk';
|
||||||
|
import { apiSlice } from '../features/api/apiSlice'
|
||||||
|
|
||||||
export const history = createBrowserHistory()
|
export const history = createBrowserHistory()
|
||||||
|
|
||||||
@@ -15,8 +16,9 @@ export default function configureStore(preloadedState) {
|
|||||||
preloadedState,
|
preloadedState,
|
||||||
compose(
|
compose(
|
||||||
applyMiddleware(
|
applyMiddleware(
|
||||||
routerMiddleware(history), // for dispatching history actions
|
createRouterMiddleware(history), // for dispatching history actions
|
||||||
thunk,
|
thunk,
|
||||||
|
apiSlice.middleware,
|
||||||
// ... other middlewares ...
|
// ... other middlewares ...
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -24,3 +26,4 @@ export default function configureStore(preloadedState) {
|
|||||||
|
|
||||||
return store
|
return store
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,27 @@
|
|||||||
|
|
||||||
// from https://github.com/supasate/connected-react-router
|
// from https://github.com/supasate/connected-react-router
|
||||||
import { combineReducers } from 'redux'
|
import { combineReducers } from 'redux'
|
||||||
import { connectRouter } from 'connected-react-router'
|
import { createRouterReducer } from '@lagunovsky/redux-react-router'
|
||||||
import systemReducer from "../System/system-reducer"
|
import systemReducer from "../System/system-reducer"
|
||||||
import talkgroupReducer from "../Talkgroups/talkgroup-reducer"
|
import talkgroupReducer from "../Talkgroups/talkgroup-reducer"
|
||||||
import groupReducer from "../Group/group-reducer"
|
import groupReducer from "../Group/group-reducer"
|
||||||
import errorReducer from "../System/error-reducer"
|
import errorReducer from "../System/error-reducer"
|
||||||
import statisticReducer from "../System/statistic-reducer"
|
import statisticReducer from "../System/statistic-reducer"
|
||||||
import permissionReducer from "../Permission/permission-reducer"
|
import permissionReducer from "../Permission/permission-reducer"
|
||||||
import userReducer from "../User/user-reducer"
|
import { userSlice, userReducer } from '../features/user/userSlice'
|
||||||
|
import {apiSlice} from "../features/api/apiSlice"
|
||||||
|
|
||||||
const createRootReducer = (history) => combineReducers({
|
const createRootReducer = (history) => combineReducers({
|
||||||
router: connectRouter(history),
|
router: createRouterReducer (history),
|
||||||
system: systemReducer,
|
system: systemReducer,
|
||||||
statistic: statisticReducer,
|
statistic: statisticReducer,
|
||||||
talkgroup: talkgroupReducer,
|
talkgroup: talkgroupReducer,
|
||||||
group: groupReducer,
|
group: groupReducer,
|
||||||
user: userReducer,
|
user: userReducer,
|
||||||
error: errorReducer,
|
error: errorReducer,
|
||||||
permission: permissionReducer
|
permission: permissionReducer,
|
||||||
|
[apiSlice.reducerPath]: apiSlice.reducer,
|
||||||
|
|
||||||
})
|
})
|
||||||
export default createRootReducer
|
export default createRootReducer
|
||||||
|
|
||||||
|
|||||||
14691
admin/yarn.lock
14691
admin/yarn.lock
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,7 @@ const root = createRoot(container);
|
|||||||
root.render(
|
root.render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<App />
|
<App store={store}/>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
</Provider>
|
</Provider>
|
||||||
)
|
)
|
||||||
@@ -2,18 +2,14 @@
|
|||||||
#
|
#
|
||||||
# docker build -t mongo .
|
# docker build -t mongo .
|
||||||
|
|
||||||
FROM mongo:4.4
|
FROM mongo:5.0
|
||||||
|
|
||||||
MAINTAINER Luke Berndt <lukekb@gmail.com>
|
MAINTAINER Luke Berndt <lukekb@gmail.com>
|
||||||
|
|
||||||
# Set timezone
|
# Set timezone
|
||||||
ENV TZ 'America/New_York'
|
ENV TZ=America/New_York
|
||||||
RUN echo $TZ > /etc/timezone && \
|
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||||
apt-get update && apt-get install -y tzdata && \
|
|
||||||
rm /etc/localtime && \
|
|
||||||
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
|
|
||||||
dpkg-reconfigure -f noninteractive tzdata && \
|
|
||||||
apt-get clean
|
|
||||||
|
|
||||||
# Add main NGINX config
|
# Add main NGINX config
|
||||||
RUN mkdir -p /app
|
RUN mkdir -p /app
|
||||||
|
|||||||
Reference in New Issue
Block a user