import React, { useEffect, useLayoutEffect, useState, useRef, useCallback, useMemo } from "react"; import { Link, useLocation, useParams, useNavigate } from 'react-router-dom'; import ListTalkgroups from "../Talkgroups/ListTalkgroups.js"; import MessageBox from "../Components/Message.js"; import ListGroups from "../Group/ListGroups.js"; import GroupModal from "../Group/GroupModalContainer.js"; import UpdatePermissionModal from "../Permission/UpdatePermissionModalContainer.js"; import AddPermissionModal from "../Permission/AddPermissionModalContainer.js"; import ErrorChart from "./ResponsiveErrorChart" import CallChart from "./ResponsiveCallChart" import { useGetSystemsQuery, useGetTalkgroupsQuery, useGetGroupsQuery, useGetErrorsQuery} from '../features/api/apiSlice' import { Button, Confirm, Icon, Form, TextArea, Header, Container, Message, List, Segment, Tab, Divider, Label } from "semantic-ui-react"; const System = (props) => { const { shortName } = useParams(); const { data: systemsData, isSuccess: isSystemsSuccess } = useGetSystemsQuery(); const { data: talkgroupsData, isSuccess: isTalkgroupsSuccess } = useGetTalkgroupsQuery(shortName); const { data: groupsData, isSuccess: isGroupsSuccess } = useGetGroupsQuery(shortName); const { data: errorsData, isSuccess: isErrorsSuccess } = useGetErrorsQuery(shortName); const [openSystemDeleteConfirm, setOpenSystemDeleteConfirm] = useState(false); const [openPermissionDeleteConfirm, setOpenPermissionDeleteConfirm] = useState(false); const [openMessage, setOpenMessage] = useState(false); const [requestMessage, setRequestMessage] = useState(""); const [groupVisible, setGroupVisible] = useState(false); const [editGroupId, setEditGroupId] = useState(false); const [errorData, setErrorData] = useState({}); const [callData, setCallData] = useState({}); const processErrors = (errors) => { var allData = []; var num = 0; const now = new Date(); var maxDate = now; var minDate = now; var minValue = 0; var maxValue = 0; var legend = []; for (var j = 0; j < errors.length; j++) { var data = []; for (var i = 0; i < errors[j].values.length; i++) { var time = new Date(errors[j].values[i].time); if (errors[j].values[i].errors > maxValue) maxValue = errors[j].values[i].errors; if (time < minDate) minDate = time; var value = { id: num++, y: errors[j].values[i].errors, x: time }; data.push(value); } const id = Math.floor(errors[j]._id / 1000) / 1000 + "MHz"; legend.push(id); var obj = { id: id, data: data }; allData.push(obj); } const errorData = { data: allData, minDate: minDate, maxDate: maxDate, minValue: minValue, maxValue: maxValue, legend: legend }; setErrorData(errorData); }; const processStatistics = (statistic) => { var callTotals = []; var errorTotals = []; const now = new Date(); var maxDate = now; var minDate = now; var minValue = 0; var maxValue = 0; var MS_PER_MINUTE = 60000; for (var j = 0; j < statistic.callTotals.length; j++) { var spotsBack = statistic.callTotals.length - j; var time = new Date(now - spotsBack * 15 * MS_PER_MINUTE); if (time < minDate) minDate = time; if (statistic.callTotals[j] > maxValue) maxValue = statistic.callTotals[j]; callTotals.push({ y: statistic.callTotals[j], x: time }); } for (var j = 0; j < statistic.errorTotals.length; j++) { var spotsBack = statistic.errorTotals.length - j; var time = new Date(now - spotsBack * 15 * MS_PER_MINUTE); if (time < minDate) minDate = time; if (statistic.errorTotals[j] > maxValue) maxValue = statistic.errorTotals[j]; errorTotals.push({ x: time, y: statistic.errorTotals[j] }); } const callData = { minDate: minDate, maxDate: maxDate, minValue: minValue, maxValue: maxValue, callTotals: callTotals, errorTotals: errorTotals }; setCallData(callData); } /* componentDidMount() { this.props.systemActions.fetchSystems(); this.props.talkgroupActions.fetchTalkgroups(this.props.shortName); this.props.groupActions.fetchGroups(this.props.shortName); this.props.errorActions.fetch(this.props.shortName); if (this.props.statistic) { this.processStatistics(this.props.statistic); } if (this.props.errors) { this.processErrors(this.props.errors); } } componentDidUpdate(prevProp) { // If we just received the error statistics for a system, for the first time, proccess them. if (this.props.errors && !prevProp.errors) { this.processErrors(this.props.errors); } // If we just received the call statistics for a system, for the first time, proccess them. if (this.props.statistic && !prevProp.statistic) { this.processStatistics(this.props.statistic); } } */ const editGroup = (groupId) => { setEditGroupId(groupId) setGroupVisible((state)=> !state) } const deleteGroup = (groupId) => { //this.props.groupActions.deleteGroup(this.props.shortName, groupId); } const reorderGroup = (oldIndex, newIndex) => { /*this.props.groupActions.reorderGroup( this.props.shortName, oldIndex, newIndex );*/ } const handleGroupClose = () => { setEditGroupId(false) setGroupVisible(false) } const handleGroupToggle = () => { setEditGroupId(false) setGroupVisible((state)=> !state) } const handleExport = () => { /* this.props.talkgroupActions .exportTalkgroups(this.props.system.shortName) .then(requestMessage => { if (requestMessage) { // report to the user is there was a problem during registration this.setState({ requestMessage }); } });*/ } const saveGroupOrder = () => { /*const order = this.props.groups.map(x => x._id); const data = { groupOrder: JSON.stringify(order) }; this.props.groupActions .saveGroupOrder(this.props.system.shortName, data) .then(requestMessage => { if (requestMessage) { } });*/ } const handleUpload = (file) => { /*this.props.talkgroupActions .importTalkgroups(this.props.system.shortName, file) .then(requestMessage => { if (requestMessage) { // report to the user is there was a problem during registration this.setState({ requestMessage }); } });*/ } const handleSystemDeleteConfirm = () => { setOpenSystemDeleteConfirm(false); /* this.props.systemActions .deleteSystem(this.props.system.shortName) .then(requestMessage => { if (requestMessage) { // report to the user is there was a problem during login this.setState({ requestMessage: requestMessage, openMessage: true }); } });*/ }; const handleSystemDeleteCancel = () => setOpenSystemDeleteConfirm(false); let system = false; if (isSystemsSuccess) { system = systemsData.systems.find(sys=>sys.shortName == shortName); } useEffect(() => { if (isSystemsSuccess) { processStatistics(systemsData.stats[shortName]) } },[isSystemsSuccess]); useEffect(() => { if (isErrorsSuccess) { processErrors(errorData) } },[isErrorsSuccess]); let fileInput = null; var location = ""; var example = ""; var groupRender = () => { }; if (system) { if (isTalkgroupsSuccess && talkgroupsData.length) { groupRender = () => (
); } else { groupRender = () => ( ); } example = '{\n\t"systems": [\n\t\t{\n\t\t\t"shortName": "' + system.shortName + '",\n\t\t\t"apiKey": "' + system.key + '"\n\t\t}\n\t],\n\t"uploadServer": "' + process.env.REACT_APP_BACKEND_SERVER + '"\n}'; switch (system.systemType) { case "state": location = system.state; break; case "city": location = system.city + ", " + system.state; break; case "county": location = system.county + ", " + system.state; break; case "international": location = system.country; break; } } const panes = [ { menuItem: "Overview", render: () => (
Location
{location}
Short Name
{system.shortName}
Description
{system.description}
) }, { menuItem: "Config", render: () => (
Configure Trunk Recorder

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

API Key
{system.key}
Short Name
{system.shortName}
Upload Server
{process.env.REACT_APP_BACKEND_SERVER}
Example