Merge branch 'master' into feature/contact

This commit is contained in:
Luke Berndt
2023-07-09 10:34:00 -04:00
committed by GitHub
7 changed files with 118 additions and 13 deletions

View File

@@ -13,7 +13,44 @@ exports.isLoggedIn = function (req, res, next) {
// -------------------------------------------
exports.listUserSystems = async function (req, res, next) {
exports.listActiveUsers = async function (req,res,next) {
if (!req.user.admin) {
res.status(401);
res.json({ success: false, message: "Not Authorized" });
return;
}
let users = {};
let fromDate = new Date(Date.now() - 60 * 60 * 24 * 30 * 1000);
const systems = await System.find({lastActive: {$gte: fromDate}}).populate('userId', "screenName").catch( err => {
console.error("Error - get_systems: " + err.message);
res.json({
success: false,
message: err
});
return;
});
for (let index = 0; index < systems.length; index++) {
const system = systems[index];
if (!users.hasOwnProperty(system.userId.toString())) {
const user = await User.findById(system.userId, "_id email firstName lastName lastLogin");
users[system.userId.toString()] = user.email;
}
}
let list = [];
for (const id in users) {
list.push(users[id]);
}
res.json(list);
return;
}
exports.listUserSystems = async function (req,res,next) {
if (!req.user.admin) {
res.status(401);
res.json({ success: false, message: "Not Authorized" });

View File

@@ -153,6 +153,7 @@ 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.get("/admin/users/active", isAdmin, systems.listActiveUsers)
app.get("/admin/users", isAdmin, systems.listUserSystems)
app.delete("/systems/:shortName", isLoggedIn, systems.deleteSystem)
app.post("/systems/:shortName", [isLoggedIn, systems.ownSystem, systems.validateSystem, systems.updateSystem])

View File

@@ -0,0 +1,37 @@
import {
Container,
Header,
Table,
Icon
} from "semantic-ui-react";
import { useGetActiveUsersQuery, } from '../features/api/apiSlice'
// ----------------------------------------------------
const ActiveUsers = () => {
const { data: users, isSuccess } = useGetActiveUsersQuery();
//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">Email of Active Users</Header>
{users &&
users.map((user) =>
<span>{user}, </span>
)}
</Container>
</div>
);
}
export default ActiveUsers;

View File

@@ -9,6 +9,7 @@ import AllSystems from "../AllSystems/AllSystems"
import ListSystems from "../System/ListSystems"
import UpdateSystem from "../System/UpdateSystem"
import CreateSystem from "../System/CreateSystem"
import ActiveUsers from "../ActiveUsers/ActiveUsers"
const App = (params) => {
@@ -22,6 +23,7 @@ const App = (params) => {
<Route path="/create-system" element={ <Restricted><CreateSystem/></Restricted>} />
<Route path="/list-systems" element={ <Restricted><ListSystems/></Restricted>} />
<Route path="/all-systems" element={ <AdminRestricted><AllSystems/></AdminRestricted>} />
<Route path="/active-users" element={ <AdminRestricted><ActiveUsers/></AdminRestricted>} />
<Route path="/" element={ <Restricted><ListSystems/></Restricted>} />
<Route render={() => (<div>Miss</div>)} />
</Routes>

View File

@@ -24,6 +24,10 @@ const Navigation = (props) => {
{process.env.REACT_APP_SITE_NAME}
</Menu.Item>
<Menu.Menu position="right">
{admin &&
<Link to="/active-users">
<Menu.Item name="active-users">Active Users</Menu.Item>
</Link> }
{admin &&
<Link to="/all-systems">
<Menu.Item name="all-systems">All Systems</Menu.Item>

View File

@@ -140,6 +140,10 @@ export const apiSlice = createApi({
// The URL for the request is '/fakeApi/posts'
query: () => ({ url: `/admin/users`, credentials: "include" })
}),
getActiveUsers: builder.query({
// The URL for the request is '/fakeApi/posts'
query: () => ({ url: `/admin/users/active`, credentials: "include" })
}),
createSystem: builder.mutation({
query: (system) => ({
url: `/systems`,
@@ -202,4 +206,4 @@ export const apiSlice = createApi({
})
// Export the auto-generated hook for the `getPosts` query endpoint
export const { useGetGroupsQuery, useGetSystemsQuery, useGetAllSystemsQuery, useGetTalkgroupsQuery, useGetErrorsQuery, useDeleteGroupMutation, useCreateGroupMutation, useCreateSystemMutation, useUpdateSystemMutation, useDeleteSystemMutation, useSaveGroupOrderMutation, useUpdateGroupMutation, useImportTalkgroupsMutation } = apiSlice
export const { useGetGroupsQuery, useGetSystemsQuery, useGetAllSystemsQuery, useGetActiveUsersQuery, useGetTalkgroupsQuery, useGetErrorsQuery, useDeleteGroupMutation, useCreateGroupMutation, useCreateSystemMutation, useUpdateSystemMutation, useDeleteSystemMutation, useSaveGroupOrderMutation, useUpdateGroupMutation, useImportTalkgroupsMutation } = apiSlice

View File

@@ -1,9 +1,27 @@
import React from "react";
import React, {useState} from "react";
import { Link } from 'react-router-dom'
import { Container, Header, Divider, Icon, Menu, Button } from "semantic-ui-react";
import { Container, Header, Divider, Icon, Menu, Button, Accordion, } from "semantic-ui-react";
const AboutComponent = () => {
const [activeIndex, setActiveIndex] = useState(-1);
const handleClick = (e, titleProps) => {
const { index } = titleProps
const newIndex = activeIndex === index ? -1 : index
setActiveIndex(newIndex);
}
const panels = [
{
key: 'feeds',
title: {content: (<span style={{fontWeight: "bold"}}>Where do the different feeds come from?</span>)},
content: [
'It is a team effort! There are contributers from around country and even internationally, that are running Trunk Recorder to capture local radio systems and sending the transmissions to OpenMHz.',
].join(' '),
}
]
return (
<div>
<Menu fixed="top">
@@ -11,30 +29,32 @@ const AboutComponent = () => {
<Link to="/systems"><Menu.Item link>Listen</Menu.Item></Link>
</Menu>
<Container text>
<Divider horizontal style={{ paddingTop: "4em", paddingBottom: "2em" }}><Header as="h1">About<Icon name='compass' /></Header></Divider>
<Divider horizontal style={{ paddingTop: "4em", paddingBottom: "2em" }}><Header as="h1">About</Header></Divider>
<p>I wrote <a href="https://github.com/robotastic/trunk-recorder">Trunk Recorder</a> because I was curious
about what my local fire station was up to and I put together the original version of OpenMHz because I
figured other people might want to listen to the recordings too.</p>
<p>The latest version of this site makes it easy for other people running Trunk Recorder to share their recrodings.
<p>The latest version of this site makes it easy for other people running Trunk Recorder to share their recordings.
I am hoping that making it easier to listen to what our local fire, police and EMS have to go through everyday will
lead to greater appreciation for all the work they do that goes largely unseen. I am personally amazed by the number
of medical runs the DC's Fire and EMS department has to cover every day, and the shocking number of them that are ODs.</p>
lead to a greater appreciation for all the work they do, which goes largely unseen.</p>
<p>Each system should have a 30 day archive. This is to help make sure things don't get overloaded and make sure I don't get a crazy bill
at the end of the month.</p>
<p>The audio from each system is archived for 30 days, so you can go back and listen to events you may have missed.</p>
<p> - Luke <a href="mailto:luke@robotastic.com?Subject=OpenMHz" target="_top">luke@robotastic.com</a> </p>
<Divider horizontal style={{ paddingTop: "4em", paddingBottom: "2em" }}><Header as="h2">Open Source</Header></Divider>
<p>Have changes you would like to suggest? Want to run your own server for your community? The source code for OpenMHz has been released:</p>
<Divider horizontal style={{ paddingTop: "4em", paddingBottom: "2em" }}><Header as="h2">100% Open Source</Header></Divider>
<p>Have changes you would like to suggest? Want to run your own server for your community? All of the code for OpenMHz is available as open source:</p>
<p><a href="https://github.com/openmhz/trunk-server"><Icon name='github' />Trunk Server</a></p>
<Divider horizontal style={{ paddingTop: "4em", paddingBottom: "2em" }}><Header as="h2">Support</Header></Divider>
<p>If OpenMHz brings you joy, think about becoming a supporter! It will cover hosting costs and help keep me focused on development.</p>
<p><a href="https://github.com/sponsors/robotastic"><Button>
<p><a href="https://github.com/sponsors/robotastic"><Button color='green'>
<Icon name='heart' />
Support
</Button></a></p>
<Divider horizontal style={{ paddingTop: "4em", paddingBottom: "2em" }}><Header as="h2">FAQ</Header></Divider>
<Accordion defaultActiveIndex={0} panels={panels} />
<Divider/>
</Container>
</div>
);