mirror of
https://github.com/openmhz/trunk-server.git
synced 2026-11-13 01:07:42 -05:00
better graphs - group modal fix - system list
This commit is contained in:
@@ -12,6 +12,66 @@ exports.isLoggedIn = function (req, res, next) {
|
||||
|
||||
// -------------------------------------------
|
||||
|
||||
exports.listAllSystems = async function (req, res, next) {
|
||||
if (!req.user.admin) {
|
||||
res.status(401);
|
||||
res.json({ success: false, message: "Not Authorized" });
|
||||
return;
|
||||
}
|
||||
|
||||
const systems = await System.find().exec();
|
||||
if (systems == null) {
|
||||
res.status(400);
|
||||
res.json({ success: false, message: err });
|
||||
return;
|
||||
}
|
||||
|
||||
let returnSys = systems.map(obj => {
|
||||
var rObj = (({
|
||||
name,
|
||||
shortName,
|
||||
description,
|
||||
systemType,
|
||||
city,
|
||||
state,
|
||||
county,
|
||||
country,
|
||||
userId,
|
||||
key,
|
||||
showScreenName,
|
||||
ignoreUnknownTalkgroup,
|
||||
lastActive,
|
||||
active
|
||||
}) => ({
|
||||
name,
|
||||
shortName,
|
||||
description,
|
||||
systemType,
|
||||
city,
|
||||
state,
|
||||
county,
|
||||
country,
|
||||
userId,
|
||||
key,
|
||||
showScreenName,
|
||||
ignoreUnknownTalkgroup,
|
||||
lastActive,
|
||||
active
|
||||
}))(obj);
|
||||
|
||||
|
||||
rObj.id = obj._id;
|
||||
return rObj;
|
||||
});
|
||||
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
systems: returnSys
|
||||
});
|
||||
return;
|
||||
};
|
||||
|
||||
exports.listSystems = async function (req, res, next) {
|
||||
const userId = new mongoose.Types.ObjectId(req.user._id);
|
||||
const systems = await System.find({ userId: userId }).exec();
|
||||
|
||||
@@ -79,7 +79,7 @@ function isOwner(req, res, next) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
function isAdmin(req, res, next) {
|
||||
if (req.params.shortName && req.user) {
|
||||
var short_name = req.params.shortName.toLowerCase();
|
||||
@@ -99,7 +99,7 @@ function isAdmin(req, res, next) {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
function isLoggedIn(req, res, next) {
|
||||
if (req.isAuthenticated()) return next();
|
||||
@@ -109,6 +109,16 @@ function isLoggedIn(req, res, next) {
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
function isAdmin(req, res, next) {
|
||||
if (req.isAuthenticated() && req.user.admin) return next();
|
||||
res.status(401).send({
|
||||
success: false,
|
||||
message: "Not Authenticated."
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
function uploadFile(req, res, next) {
|
||||
const upload = multer({dest: 'uploads/'}).single('file');
|
||||
|
||||
@@ -142,6 +152,7 @@ app.post("/groups/:shortName/:groupId?", isLoggedIn, groups.upsertGroup);
|
||||
app.get("/groups/:shortName/:groupId?", isLoggedIn, groups.getGroups);
|
||||
app.delete("/groups/:shortName/:groupId", isLoggedIn, groups.deleteGroup);
|
||||
app.get("/systems", isLoggedIn, systems.listSystems)
|
||||
app.get("/admin/systems", isAdmin, systems.listAllSystems)
|
||||
app.delete("/systems/:shortName", isLoggedIn, systems.deleteSystem)
|
||||
app.post("/systems/:shortName", [isLoggedIn, systems.ownSystem, systems.validateSystem, systems.updateSystem])
|
||||
app.post("/systems", [isLoggedIn, systems.uniqueShortName, systems.validateSystem, systems.createSystem])
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
var mongoose = require('mongoose');
|
||||
var bcrypt = require('bcrypt');
|
||||
var User = require('./user');
|
||||
|
||||
var systemSchema = mongoose.Schema({
|
||||
name: String,
|
||||
@@ -12,7 +13,9 @@ var systemSchema = mongoose.Schema({
|
||||
description: String,
|
||||
showScreenName: Boolean,
|
||||
ignoreUnknownTalkgroup : Boolean,
|
||||
userId: mongoose.Schema.Types.ObjectId,
|
||||
active: {type: Boolean, default: false},
|
||||
lastActive: Date,
|
||||
userId: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
|
||||
key: String
|
||||
});
|
||||
|
||||
|
||||
58
admin/src/AllSystems/AllSystems.js
Normal file
58
admin/src/AllSystems/AllSystems.js
Normal file
@@ -0,0 +1,58 @@
|
||||
import {
|
||||
Container,
|
||||
Divider,
|
||||
Header,
|
||||
Table
|
||||
} from "semantic-ui-react";
|
||||
import { useGetAllSystemsQuery, } from '../features/api/apiSlice'
|
||||
|
||||
|
||||
// ----------------------------------------------------
|
||||
const ListSystems = () => {
|
||||
const { data, isSuccess } = useGetAllSystemsQuery();
|
||||
let systems = false;
|
||||
if (isSuccess) {
|
||||
systems = data.systems;
|
||||
}
|
||||
|
||||
//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
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Container>
|
||||
<Header as="h1">Radio Systems</Header>
|
||||
|
||||
|
||||
{systems &&
|
||||
systems.map((system) =>
|
||||
<Table celled selectable>
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
<Table.HeaderCell>ShortName</Table.HeaderCell>
|
||||
<Table.HeaderCell>Name</Table.HeaderCell>
|
||||
<Table.HeaderCell>Last Active</Table.HeaderCell>
|
||||
<Table.HeaderCell>Owner</Table.HeaderCell>
|
||||
<Table.HeaderCell>Email</Table.HeaderCell>
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
|
||||
<Table.Body>
|
||||
<Table.Row>
|
||||
<Table.Cell>{system.shortName}</Table.Cell>
|
||||
<Table.Cell>{system.name}</Table.Cell>
|
||||
<Table.Cell>{system.lastActive}</Table.Cell>
|
||||
<Table.Cell>{system.userId.firstName} {system.userId.lastName}</Table.Cell>
|
||||
<Table.Cell>{system.userId.email}</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table.Body>
|
||||
</Table>
|
||||
)}
|
||||
|
||||
</Container>
|
||||
</div>
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
export default ListSystems;
|
||||
@@ -1,7 +1,7 @@
|
||||
import Navigation from "./Navigation"
|
||||
import { Routes, Route } from 'react-router-dom';
|
||||
|
||||
import Restricted from "./Restricted"
|
||||
import {AdminRestricted, Restricted} from "./Restricted"
|
||||
|
||||
import About from "../Components/About"
|
||||
import System from "../System/System"
|
||||
@@ -20,6 +20,7 @@ const App = (params) => {
|
||||
<Route path="/update-system/:shortName" element={ <Restricted><UpdateSystem/></Restricted>} />
|
||||
<Route path="/create-system" element={ <Restricted><CreateSystem/></Restricted>} />
|
||||
<Route path="/list-systems" element={ <Restricted><ListSystems/></Restricted>} />
|
||||
<Route path="/all-systems" element={ <AdminRestricted><ListSystems/></AdminRestricted>} />
|
||||
<Route path="/" element={ <Restricted><ListSystems/></Restricted>} />
|
||||
<Route render={() => (<div>Miss</div>)} />
|
||||
</Routes>
|
||||
|
||||
@@ -9,7 +9,7 @@ const navStyle = {
|
||||
|
||||
const Navigation = (props) => {
|
||||
const dispatch = useDispatch();
|
||||
const { email } = useSelector((state) => state.user);
|
||||
const { email, admin } = useSelector((state) => state.user);
|
||||
|
||||
const logout = event => {
|
||||
event.preventDefault();
|
||||
@@ -24,6 +24,11 @@ const Navigation = (props) => {
|
||||
{process.env.REACT_APP_SITE_NAME}
|
||||
</Menu.Item>
|
||||
<Menu.Menu position="right">
|
||||
{admin &&
|
||||
<Link to="/all-systems">
|
||||
<Menu.Item name="all-systems">All Systems</Menu.Item>
|
||||
</Link>
|
||||
}
|
||||
<Link to="/list-systems">
|
||||
<Menu.Item name="systems"> Systems</Menu.Item>
|
||||
</Link>
|
||||
|
||||
@@ -7,7 +7,7 @@ import { authenticateUser } from "../features/user/userSlice";
|
||||
* Higher-order component (HOC) to wrap restricted pages
|
||||
*/
|
||||
|
||||
const Restricted = ({children }) => {
|
||||
export const Restricted = ({children }) => {
|
||||
const { authenticated, hasAuthenticated } = useSelector((state) => state.user);
|
||||
const dispatch = useDispatch();
|
||||
useEffect(() => {
|
||||
@@ -26,4 +26,23 @@ const Restricted = ({children }) => {
|
||||
|
||||
};
|
||||
|
||||
export const AdminRestricted = ({children }) => {
|
||||
const { authenticated, hasAuthenticated, admin } = useSelector((state) => state.user);
|
||||
const dispatch = useDispatch();
|
||||
useEffect(() => {
|
||||
dispatch(authenticateUser({}));
|
||||
},[]);
|
||||
|
||||
if (hasAuthenticated) {
|
||||
if (authenticated && admin) {
|
||||
return children;;
|
||||
}
|
||||
else {
|
||||
window.location = process.env.REACT_APP_ACCOUNT_SERVER + "/login?nextLocation=admin";
|
||||
}
|
||||
}
|
||||
return <div/>
|
||||
|
||||
};
|
||||
|
||||
export default Restricted
|
||||
@@ -77,7 +77,7 @@ const GroupModal = (props) => {
|
||||
}
|
||||
},[props.editGroupId, props.talkgroups]);
|
||||
|
||||
const removeTalkgroup = (index) => {
|
||||
const removeTalkgroup = (event, index) => {
|
||||
const item = {
|
||||
num: group.items[index].num,
|
||||
description: group.items[index].description
|
||||
|
||||
@@ -136,6 +136,10 @@ export const apiSlice = createApi({
|
||||
// The URL for the request is '/fakeApi/posts'
|
||||
query: () => ({ url: `/systems`, credentials: "include" })
|
||||
}),
|
||||
getAllSystems: builder.query({
|
||||
// The URL for the request is '/fakeApi/posts'
|
||||
query: () => ({ url: `/admin/systems`, credentials: "include" })
|
||||
}),
|
||||
createSystem: builder.mutation({
|
||||
query: (system) => ({
|
||||
url: `/systems`,
|
||||
@@ -198,4 +202,4 @@ export const apiSlice = createApi({
|
||||
})
|
||||
|
||||
// Export the auto-generated hook for the `getPosts` query endpoint
|
||||
export const { useGetGroupsQuery, useGetSystemsQuery, useGetTalkgroupsQuery, useGetErrorsQuery, useDeleteGroupMutation, useCreateGroupMutation, useCreateSystemMutation, useUpdateSystemMutation, useDeleteSystemMutation, useSaveGroupOrderMutation, useUpdateGroupMutation, useImportTalkgroupsMutation } = apiSlice
|
||||
export const { useGetGroupsQuery, useGetSystemsQuery, useGetAllSystemsQuery, useGetTalkgroupsQuery, useGetErrorsQuery, useDeleteGroupMutation, useCreateGroupMutation, useCreateSystemMutation, useUpdateSystemMutation, useDeleteSystemMutation, useSaveGroupOrderMutation, useUpdateGroupMutation, useImportTalkgroupsMutation } = apiSlice
|
||||
|
||||
Reference in New Issue
Block a user