diff --git a/account/server/controllers/systems.js b/account/server/controllers/systems.js index 8c6a83b..8ce71bb 100644 --- a/account/server/controllers/systems.js +++ b/account/server/controllers/systems.js @@ -18,6 +18,7 @@ exports.getUserSystems = async function (_id) { name, shortName, description, + status, systemType, city, state, @@ -31,6 +32,7 @@ exports.getUserSystems = async function (_id) { name, shortName, description, + status, systemType, city, state, diff --git a/account/server/models/system.js b/account/server/models/system.js index ca6cf93..a2aa65e 100644 --- a/account/server/models/system.js +++ b/account/server/models/system.js @@ -10,6 +10,7 @@ var systemSchema = mongoose.Schema({ city: String, state: String, description: String, + status: String, showScreenName: Boolean, planType: {type: Number, default: 0}, userId: mongoose.Schema.Types.ObjectId, diff --git a/admin/server/controllers/systems.js b/admin/server/controllers/systems.js index 05d5ac7..d7d3b01 100644 --- a/admin/server/controllers/systems.js +++ b/admin/server/controllers/systems.js @@ -62,7 +62,7 @@ exports.listUserSystems = async function (req,res,next) { for (let index = 0; index < users.length; index++) { let user = users[index].toObject(); const userId = new mongoose.Types.ObjectId(user._id); - const systems = await System.find({ userId: userId }, "name shortName description systemType city state county country lastActive"); + const systems = await System.find({ userId: userId }, "name shortName description status systemType city state county country lastActive"); user["systems"] = systems; list.push(user); @@ -90,6 +90,7 @@ exports.listAllSystems = async function (req, res, next) { name, shortName, description, + status, systemType, city, state, @@ -106,6 +107,7 @@ exports.listAllSystems = async function (req, res, next) { name, shortName, description, + status, systemType, city, state, @@ -154,6 +156,7 @@ exports.listSystems = async function (req, res, next) { name, shortName, description, + status, systemType, city, state, @@ -168,6 +171,7 @@ exports.listSystems = async function (req, res, next) { name, shortName, description, + status, systemType, city, state, @@ -360,6 +364,7 @@ exports.updateSystem = async function (req, res, next) { res.locals.system.county = res.locals.county; res.locals.system.country = res.locals.country; res.locals.system.description = res.locals.description; + res.locals.system.status = res.locals.status; res.locals.system.systemType = res.locals.systemType; res.locals.system.showScreenName = res.locals.showScreenName; res.locals.system.allowContact = res.locals.allowContact; @@ -378,6 +383,7 @@ exports.updateSystem = async function (req, res, next) { name, shortName, description, + status, systemType, city, state, @@ -392,6 +398,7 @@ exports.updateSystem = async function (req, res, next) { name, shortName, description, + status, systemType, city, state, @@ -429,7 +436,7 @@ exports.validateSystem = async function (req, res, next) { res.locals.name = req.body.name.replace(/[^\w\s\.\,\-\_]/gi, ''); if (!req.body.description || (req.body.description.length < 2)) { - console.error("ERROR: Validate System - req.body.description"); + console.error("ERROR: Validate System - req.body.description: " + req.body.description); res.status(500) res.json({ success: false, @@ -437,7 +444,9 @@ exports.validateSystem = async function (req, res, next) { }); return; } - res.locals.description = req.body.description.replace(/[^\w\s\.\,\-\_]/gi, ''); + res.locals.description = req.body.description.replace(/[^\w\s\.\,\-\_\(\)\'\"\!\?\*\&\^\%\$\#\@\r\n\t\`\~\[\]\/\\]/gi, ''); + + res.locals.status = req.body.status.replace(/[^\w\s\.\,\-\_\(\)\'\"\!\?\*\&\^\%\$\#\@\r\n\t\`\~\[\]\/\\]/gi, ''); if (!req.body.shortName || (req.body.shortName.length < 2)) { console.error("ERROR: Validate System - req.body.shortName"); @@ -547,6 +556,7 @@ exports.createSystem = async function (req, res, next) { name, shortName, description, + status, systemType, city, state, @@ -559,6 +569,7 @@ exports.createSystem = async function (req, res, next) { name, shortName, description, + status, systemType, city, state, @@ -585,6 +596,7 @@ exports.createSystem = async function (req, res, next) { name, shortName, description, + status, systemType, city, state, @@ -599,6 +611,7 @@ exports.createSystem = async function (req, res, next) { name, shortName, description, + status, systemType, city, state, diff --git a/admin/server/models/system.js b/admin/server/models/system.js index b19efe9..92c99cb 100644 --- a/admin/server/models/system.js +++ b/admin/server/models/system.js @@ -11,6 +11,7 @@ var systemSchema = mongoose.Schema({ city: String, state: String, description: String, + status: String, showScreenName: Boolean, allowContact: { type: Boolean, diff --git a/admin/src/System/System.js b/admin/src/System/System.js index 11d5a8e..a81750f 100644 --- a/admin/src/System/System.js +++ b/admin/src/System/System.js @@ -236,7 +236,6 @@ const System = () => { setGroupOrder(newOrder); } }, [groupsData]) - useEffect(() => { if (isSystemsSuccess && systemsData.stats[shortName]) { processStatistics(systemsData.stats[shortName]) @@ -328,7 +327,12 @@ const System = () => {
Description
{system.description} - + {system.status.length>0 && + +
Status Message
+ {system.status} +
+ } - - - - - - - - - - -
- All The Calls -
-

Every call, on every talkgroup is recorded

-
- -
- - Go back in time -
-

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

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

- Most large cities use trunked radio systems to get the most use out of their assigned radio spectrum. With trunked systems, the transmission are constantly hopping to different frequencies. Using a cheap Software Defined Radio (SDR), it is possible capture all of the transmission on a system. - Instead of scanning to a single frequency, SDR capturea wide swathes of spectrum, covering all of the frequencies a system could use. -

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

- Join us! Record a local radio system and share it with the world. If you have a spare computer, it is easy to get started. With a $25 SDR or two, you can capture an entire system. - It does take a little bit of work to get things setup, but we are here to help and answer questions. -

- - - -
-
- - - - - - - - - -
- The End -
-
- + )} + + + + + + +
+
+
+ + + + + + + + + + + + + - - - - - - - ); + + + + +
+ All The Calls +
+

Every call, on every talkgroup is recorded

+
+ +
+ + Go back in time +
+

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

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

+ Most large cities use trunked radio systems to get the most use out of their assigned radio spectrum. With trunked systems, the transmission are constantly hopping to different frequencies. Using a cheap Software Defined Radio (SDR), it is possible capture all of the transmission on a system. + Instead of scanning to a single frequency, SDR capturea wide swathes of spectrum, covering all of the frequencies a system could use. +

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

+ Join us! Record a local radio system and share it with the world. If you have a spare computer, it is easy to get started. With a $25 SDR or two, you can capture an entire system. + It does take a little bit of work to get things setup, but we are here to help and answer questions. +

+ + + +
+
+ + + + + + + + + +
+ The End +
+
+ + + + +
+
+
+
+ + + ); } diff --git a/frontend/src/System/SystemCard.js b/frontend/src/System/SystemCard.js index 1e44199..fc2aa9a 100644 --- a/frontend/src/System/SystemCard.js +++ b/frontend/src/System/SystemCard.js @@ -3,114 +3,143 @@ import { Card, Icon, Label, - Grid + Grid, + Segment, + Popup, + Button } from "semantic-ui-react"; -function SystemCard (props) { +function SystemCard(props) { + + const { system, keepShort, onClick, onContactClick } = props; + var location = ""; + var clientCount = ""; + var callAvg = ""; + let description = system.description; + let statusMessage = ""; - const {system, keepShort, onClick, onContactClick} = props; - var location = ""; - var clientCount = ""; - var callAvg = ""; - let description = system.description; - - - - const handleContactClick = (event) => { - event.stopPropagation(); - onContactClick(system); + if (system.status && system.status.length > 0) { + statusMessage = system.status + if (statusMessage.length > 25) { + statusMessage = statusMessage.substring(0, 25) + "..."; } + } - const onCardClick = (event) => { - onClick(); - } - if (keepShort && (description.length > 100)) { - description = description.substring(0, 96) + "..."; - } - if (system.callAvg) { - callAvg = Math.round(system.callAvg * 10) / 10 + "/min" - } - if (system.clientCount === 1) { - clientCount = "1 listener"; - } else if (system.clientCount > 1) { - clientCount = system.clientCount + " listeners" - } - let status = (<>) - if (system.active) { - status = ( - + const handleContactClick = (event) => { + event.stopPropagation(); + onContactClick(system); + } + + const onCardClick = (event) => { + onClick(); + } + + if (keepShort && (description.length > 100)) { + description = description.substring(0, 96) + "..."; + } + + + + + if (keepShort) { + statusMessage = ""; + } + + if (system.callAvg) { + callAvg = Math.round(system.callAvg * 10) / 10 + "/min" + } + if (system.clientCount === 1) { + clientCount = "1 listener"; + } else if (system.clientCount > 1) { + clientCount = system.clientCount + " listeners" + } + + let status = (<>) + + if (system.active) { + status = ( + {clientCount &&
{clientCount}
}
{callAvg &&
{callAvg}
} -
-
-
- ) - } else { - const lastActive = new Date(system.lastActive); - status = ( - - - - Last Active {lastActive.toLocaleDateString()} - - - ) - } +
+ ) + } else { + const lastActive = new Date(system.lastActive); + status = ( + + + + Last Active {lastActive.toLocaleDateString()} + + + - if (system) { - switch (system.systemType) { - case "state": - location = system.state; - break; - case "city": - location = system.city + ", " + system.state; - break; - case "county": - location = system.county + ", " + system.state; - break; - case "international": - location = system.country; - break; - default: - location = system.city + ", " + system.state; - } + ) + } + + if (system) { + switch (system.systemType) { + case "state": + location = system.state; + break; + case "city": + location = system.city + ", " + system.state; + break; + case "county": + location = system.county + ", " + system.state; + break; + case "international": + location = system.country; + break; + default: + location = system.city + ", " + system.state; } - return ( - - - {system.name} - {location} - - + } + return ( + + + {system.name} + {location} + + - + {system.screenName && } {system.allowContact && } - - + + + + + {description} + + + {statusMessage.length && - {description} + + {statusMessage}} /> + - - - - - {status} - - - ); + } + + + + + {status} + + + ); } export default SystemCard; diff --git a/nginx-proxy/test/vhosts/site.template b/nginx-proxy/test/vhosts/site.template index af1b333..751e7bf 100644 --- a/nginx-proxy/test/vhosts/site.template +++ b/nginx-proxy/test/vhosts/site.template @@ -1,12 +1,3 @@ -server { - listen 80; - server_name account.${DOMAIN_NAME} api.${DOMAIN_NAME} admin.${DOMAIN_NAME} www.${DOMAIN_NAME} ${DOMAIN_NAME}; - - location /.well-known/acme-challenge/ { - root /var/www/certbot; - } -} - server { listen 80;