mirror of
https://github.com/openmhz/trunk-server.git
synced 2026-11-13 09:17:30 -05:00
@@ -6,6 +6,7 @@ import CallInfo from "./components/CallInfo";
|
|||||||
import ListCalls from "./components/ListCalls";
|
import ListCalls from "./components/ListCalls";
|
||||||
import { useSelector, useDispatch } from 'react-redux'
|
import { useSelector, useDispatch } from 'react-redux'
|
||||||
import { useGetTalkgroupsQuery } from '../features/api/apiSlice'
|
import { useGetTalkgroupsQuery } from '../features/api/apiSlice'
|
||||||
|
import { playedCall } from "../features/calls/callsSlice";
|
||||||
import { useInView } from 'react-intersection-observer';
|
import { useInView } from 'react-intersection-observer';
|
||||||
import {
|
import {
|
||||||
Container,
|
Container,
|
||||||
@@ -72,6 +73,7 @@ function CallPlayer(props) {
|
|||||||
|
|
||||||
const playCall = (data) => {
|
const playCall = (data) => {
|
||||||
setCurrentCall(data.call);
|
setCurrentCall(data.call);
|
||||||
|
dispatch(playedCall(data.call._id));
|
||||||
setIsPlaying(true);
|
setIsPlaying(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,6 +85,7 @@ function CallPlayer(props) {
|
|||||||
const nextCall = callsData.entities[nextCallId];
|
const nextCall = callsData.entities[nextCallId];
|
||||||
|
|
||||||
setCurrentCall(nextCall);
|
setCurrentCall(nextCall);
|
||||||
|
dispatch(playedCall(nextCall._id));
|
||||||
setIsPlaying(true);
|
setIsPlaying(true);
|
||||||
} else {
|
} else {
|
||||||
setIsPlaying(false);
|
setIsPlaying(false);
|
||||||
@@ -93,7 +96,7 @@ function CallPlayer(props) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (loadNewerInView && callsData && (callsData.ids.length > 0)) {
|
if (!live && loadNewerInView && callsData && (callsData.ids.length > 0)) {
|
||||||
handleNewer();
|
handleNewer();
|
||||||
}
|
}
|
||||||
}, [loadNewerInView]);
|
}, [loadNewerInView]);
|
||||||
@@ -115,7 +118,9 @@ function CallPlayer(props) {
|
|||||||
if (selectCallId && callsData && !isPlaying && autoPlay) {
|
if (selectCallId && callsData && !isPlaying && autoPlay) {
|
||||||
const call = callsData.entities[selectCallId];
|
const call = callsData.entities[selectCallId];
|
||||||
if (call) {
|
if (call) {
|
||||||
|
setIsPlaying(true);
|
||||||
setCurrentCall(call);
|
setCurrentCall(call);
|
||||||
|
dispatch(playedCall(call._id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [selectCallId, callsData])
|
}, [selectCallId, callsData])
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ import CallPlayer from "./CallPlayer";
|
|||||||
import { useSelector, useDispatch } from 'react-redux'
|
import { useSelector, useDispatch } from 'react-redux'
|
||||||
import { setLive, setFilter, setDateFilter } from "../features/callPlayer/callPlayerSlice";
|
import { setLive, setFilter, setDateFilter } from "../features/callPlayer/callPlayerSlice";
|
||||||
import { getCalls, addCall, getOlderCalls, getNewerCalls } from "../features/calls/callsSlice";
|
import { getCalls, addCall, getOlderCalls, getNewerCalls } from "../features/calls/callsSlice";
|
||||||
import { useGetGroupsQuery, useGetTalkgroupsQuery } from '../features/api/apiSlice'
|
import { useGetGroupsQuery, useGetSystemsQuery, } from '../features/api/apiSlice'
|
||||||
|
import { selectSystem } from "../features/systems/systemsSlice";
|
||||||
import {
|
import {
|
||||||
Container,
|
Container,
|
||||||
Label,
|
Label,
|
||||||
@@ -30,9 +30,10 @@ const socket = io(process.env.REACT_APP_BACKEND_SERVER);
|
|||||||
function Calls(props) {
|
function Calls(props) {
|
||||||
|
|
||||||
const { shortName } = useParams();
|
const { shortName } = useParams();
|
||||||
|
const { data: allSystems, isSuccess } = useGetSystemsQuery();
|
||||||
const { data: groupsData, isSuccess: isGroupsSuccess } = useGetGroupsQuery(shortName);
|
const { data: groupsData, isSuccess: isGroupsSuccess } = useGetGroupsQuery(shortName);
|
||||||
const { loading: callsLoading, data: callsData } = useSelector((state) => state.calls);
|
const { loading: callsLoading, data: callsData } = useSelector((state) => state.calls);
|
||||||
|
|
||||||
const [autoPlay, setAutoPlay] = useState(true);
|
const [autoPlay, setAutoPlay] = useState(true);
|
||||||
const [currentCall, setCurrentCall] = useState(false);
|
const [currentCall, setCurrentCall] = useState(false);
|
||||||
const [urlOptions, setUrlOptions] = useState(false);
|
const [urlOptions, setUrlOptions] = useState(false);
|
||||||
@@ -61,12 +62,15 @@ function Calls(props) {
|
|||||||
const pathname = useLocation().pathname;
|
const pathname = useLocation().pathname;
|
||||||
|
|
||||||
let currentCallId = false;
|
let currentCallId = false;
|
||||||
|
let system = false;
|
||||||
|
|
||||||
if (currentCall) {
|
if (currentCall) {
|
||||||
currentCallId = currentCall._id;
|
currentCallId = currentCall._id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (allSystems) {
|
||||||
|
system = allSystems.systems.find( (system) => system.shortName === shortName)
|
||||||
|
}
|
||||||
|
|
||||||
const handlePusherClick = () => {
|
const handlePusherClick = () => {
|
||||||
if (sidebarOpened) setSidebarOpened(false);
|
if (sidebarOpened) setSidebarOpened(false);
|
||||||
@@ -210,8 +214,10 @@ useLayoutEffect(() => {
|
|||||||
if (pageYOffset.current) {
|
if (pageYOffset.current) {
|
||||||
const scrollAmount = parseInt(positionRef.current.clientHeight) - parseInt(pageYOffset.current.position);
|
const scrollAmount = parseInt(positionRef.current.clientHeight) - parseInt(pageYOffset.current.position);
|
||||||
if (pageYOffset.current.direction == "top") {
|
if (pageYOffset.current.direction == "top") {
|
||||||
window.scrollBy({left: 0, top: scrollAmount, behavior: "auto"});
|
window.scrollBy({left: 0, top: scrollAmount, behavior: "auto"});
|
||||||
|
pageYOffset.current = {direction: "bottom", position: positionRef.current.clientHeight}; // reset PageY to be the current height incase callsData changes for other reasons
|
||||||
} else {
|
} else {
|
||||||
|
pageYOffset.current = {direction: "bottom", position: positionRef.current.clientHeight};
|
||||||
//window.scrollBy(0, -1 * scrollAmount);
|
//window.scrollBy(0, -1 * scrollAmount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -381,7 +387,7 @@ useLayoutEffect(() => {
|
|||||||
<Label horizontal={true} color="grey" className="desktop-only">{filterLabel}</Label>
|
<Label horizontal={true} color="grey" className="desktop-only">{filterLabel}</Label>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Container className="desktop-only" textAlign='center' style={{ fontSize: '1.5rem', paddingLeft: '1em', paddingTop: '.5em' }}>
|
<Container className="desktop-only" textAlign='center' style={{ fontSize: '1.5rem', paddingLeft: '1em', paddingTop: '.5em' }}>
|
||||||
{/*system && system.name*/}
|
{system && system.name}
|
||||||
</Container>
|
</Container>
|
||||||
<Menu.Menu position="right">
|
<Menu.Menu position="right">
|
||||||
<Menu.Item name='archive-btn' onClick={handleCalendarToggle} active={!live}>
|
<Menu.Item name='archive-btn' onClick={handleCalendarToggle} active={!live}>
|
||||||
|
|||||||
@@ -89,11 +89,21 @@ const CallItem = (props) => {
|
|||||||
} else {
|
} else {
|
||||||
talkgroup = talkgroups.talkgroups[call.talkgroupNum].description;
|
talkgroup = talkgroups.talkgroups[call.talkgroupNum].description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let playStatus = (<></>)
|
||||||
|
if (activeCall) {
|
||||||
|
playStatus = (<Icon name="play" size='small' color="green"/>)
|
||||||
|
|
||||||
|
} else if (!call.played) {
|
||||||
|
playStatus = (<Icon name="chevron right" size='small' disabled/>)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Table.Row draggable="true" onClick={(e) => props.onClick({ call: call }, e)} {...rowSelected} onDragStart={onDragStart} data-callid={call._id}>
|
<Table.Row draggable="true" onClick={(e) => props.onClick({ call: call }, e)} {...rowSelected} onDragStart={onDragStart} data-callid={call._id}>
|
||||||
<Table.Cell> {call.len} </Table.Cell>
|
<Table.Cell>{playStatus}</Table.Cell>
|
||||||
<Table.Cell> {talkgroup} </Table.Cell>
|
<Table.Cell>{call.len}</Table.Cell>
|
||||||
<Table.Cell> {time.toLocaleTimeString()} </Table.Cell>
|
<Table.Cell>{talkgroup}</Table.Cell>
|
||||||
|
<Table.Cell>{time.toLocaleTimeString()}</Table.Cell>
|
||||||
<Table.Cell onMouseEnter={() => setStarVisible(true)} onMouseLeave={() => setStarVisible(false)} onClick={handleStarClicked}>{starButton}</Table.Cell>
|
<Table.Cell onMouseEnter={() => setStarVisible(true)} onMouseLeave={() => setStarVisible(false)} onClick={handleStarClicked}>{starButton}</Table.Cell>
|
||||||
</Table.Row>
|
</Table.Row>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ const ListCalls = (props) => {
|
|||||||
<Table id="calls" unstackable >
|
<Table id="calls" unstackable >
|
||||||
<Table.Header >
|
<Table.Header >
|
||||||
<Table.Row>
|
<Table.Row>
|
||||||
|
<Table.HeaderCell> </Table.HeaderCell>
|
||||||
<Table.HeaderCell>Len</Table.HeaderCell>
|
<Table.HeaderCell>Len</Table.HeaderCell>
|
||||||
<Table.HeaderCell>Talkgroup</Table.HeaderCell>
|
<Table.HeaderCell>Talkgroup</Table.HeaderCell>
|
||||||
<Table.HeaderCell>Time</Table.HeaderCell>
|
<Table.HeaderCell>Time</Table.HeaderCell>
|
||||||
|
|||||||
@@ -18,9 +18,20 @@ const MediaPlayer = (props) => {
|
|||||||
const [isPlaying, setIsPlaying] = useState(false);
|
const [isPlaying, setIsPlaying] = useState(false);
|
||||||
const parentHandlePlayPause = props.onPlayPause
|
const parentHandlePlayPause = props.onPlayPause
|
||||||
|
|
||||||
const handlePause = () => { setIsPlaying(false); parentHandlePlayPause(false); }
|
const handlePause = () => { setIsPlaying(false); }
|
||||||
const handlePlay = () => { setIsPlaying(true); parentHandlePlayPause(true); }
|
const handlePlay = () => { setIsPlaying(true); }
|
||||||
const playPause = () => { const audio = audioRef.current.audioEl.current; if (isPlaying) { audio.pause(); } else { audio.play(); } }
|
const playPause = () => {
|
||||||
|
const audio = audioRef.current.audioEl.current;
|
||||||
|
if (isPlaying) {
|
||||||
|
setIsPlaying(false);
|
||||||
|
parentHandlePlayPause(false);
|
||||||
|
audio.pause();
|
||||||
|
} else {
|
||||||
|
setIsPlaying(true);
|
||||||
|
parentHandlePlayPause(true);
|
||||||
|
audio.play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const call = props.call;
|
const call = props.call;
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
return (
|
return (
|
||||||
<Menu fixed="top">
|
<Menu fixed="top">
|
||||||
<Link to="/"><Menu.Item link><Icon name='arrow left' /> Home</Menu.Item></Link>
|
<Link to="/"><Menu.Item link><Icon name='arrow left' /> Home</Menu.Item></Link>
|
||||||
<Link to="/systems"><Menu.Item link>Listen</Menu.Item></Link>
|
<Link to="/systems"><Menu.Item link>Systems</Menu.Item></Link>
|
||||||
<Link to="/events"><Menu.Item link>Events</Menu.Item></Link>
|
<Link to="/events"><Menu.Item link>Events</Menu.Item></Link>
|
||||||
<Link to="/about"><Menu.Item link>About</Menu.Item></Link>
|
<Link to="/about"><Menu.Item link>About</Menu.Item></Link>
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|||||||
@@ -52,33 +52,30 @@ const ListSystems = (props) => {
|
|||||||
<div ref={contextRef}>
|
<div ref={contextRef}>
|
||||||
<NavBar />
|
<NavBar />
|
||||||
<Container >
|
<Container >
|
||||||
|
|
||||||
<Divider horizontal style={{ paddingTop: "5em", paddingBottom: "2em" }}><Header as="h1">Radio Systems<Icon name='rss' /></Header></Divider>
|
<Divider horizontal style={{ paddingTop: "5em", paddingBottom: "2em" }}><Header as="h1">Radio Systems<Icon name='rss' /></Header></Divider>
|
||||||
|
|
||||||
<Grid centered columns={2}>
|
<Grid centered columns={2}>
|
||||||
<Grid.Column width="15">
|
<Grid.Column width="15">
|
||||||
<List horizontal>
|
<List horizontal>
|
||||||
{stateList}
|
{stateList}
|
||||||
<List.Item>
|
<List.Item>
|
||||||
<List.Content>
|
<List.Content>
|
||||||
<List.Header><a href="#international">International</a></List.Header>
|
<List.Header><a href="#international">International</a></List.Header>
|
||||||
</List.Content>
|
</List.Content>
|
||||||
</List.Item>
|
</List.Item>
|
||||||
</List>
|
</List>
|
||||||
{systemsByState}
|
{systemsByState}
|
||||||
{international}
|
{international}
|
||||||
|
</Grid.Column>
|
||||||
</Grid.Column>
|
<Grid.Column width="1" only='computer'>
|
||||||
<Grid.Column width="1">
|
<Sticky offset={60} context={contextRef}>
|
||||||
<Sticky offset={60} context={contextRef}>
|
<Segment>
|
||||||
<Segment>
|
<List >
|
||||||
<List >
|
{stateList}
|
||||||
{stateList}
|
</List>
|
||||||
</List>
|
</Segment>
|
||||||
</Segment>
|
</Sticky>
|
||||||
</Sticky>
|
</Grid.Column>
|
||||||
</Grid.Column>
|
</Grid>
|
||||||
</Grid>
|
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -65,8 +65,7 @@ const initialState = {
|
|||||||
loading: false,
|
loading: false,
|
||||||
data: callsAdapter.getInitialState(),
|
data: callsAdapter.getInitialState(),
|
||||||
oldestCallTime: now,
|
oldestCallTime: now,
|
||||||
newestCallTime: now,
|
newestCallTime: now
|
||||||
adjustCallScroll: false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildUrlParams(a) {
|
function buildUrlParams(a) {
|
||||||
@@ -201,9 +200,12 @@ export const callsSlice = createSlice({
|
|||||||
initialState,
|
initialState,
|
||||||
reducers: {
|
reducers: {
|
||||||
addCall: (state, action) => {
|
addCall: (state, action) => {
|
||||||
state.data = callsAdapter.addOne(state.data, action.payload)
|
const call = {...action.payload, played: false}
|
||||||
state.adjustCallScroll = true;
|
state.data = callsAdapter.addOne(state.data, call)
|
||||||
},
|
},
|
||||||
|
playedCall: (state,action) => {
|
||||||
|
state.data = callsAdapter.updateOne(state.data,{id: action.payload, changes: {played: true}});
|
||||||
|
}
|
||||||
},
|
},
|
||||||
extraReducers: {
|
extraReducers: {
|
||||||
[getCalls.pending]: (state) => {
|
[getCalls.pending]: (state) => {
|
||||||
@@ -214,7 +216,8 @@ export const callsSlice = createSlice({
|
|||||||
},
|
},
|
||||||
[getCalls.fulfilled]: (state, {payload}) => {
|
[getCalls.fulfilled]: (state, {payload}) => {
|
||||||
state.loading = false;
|
state.loading = false;
|
||||||
state.data = callsAdapter.setAll(state.data, payload.calls)
|
const calls = payload.calls.map( (call) => ({...call, played: false}));
|
||||||
|
state.data = callsAdapter.setAll(state.data, calls)
|
||||||
if (state.data && (state.data.ids.length > 0)) {
|
if (state.data && (state.data.ids.length > 0)) {
|
||||||
const first = state.data.ids[0]
|
const first = state.data.ids[0]
|
||||||
const firstTime = state.data.entities[first].time;
|
const firstTime = state.data.entities[first].time;
|
||||||
@@ -232,7 +235,8 @@ export const callsSlice = createSlice({
|
|||||||
},
|
},
|
||||||
[getOlderCalls.fulfilled]: (state, {payload}) => {
|
[getOlderCalls.fulfilled]: (state, {payload}) => {
|
||||||
state.loading = false;
|
state.loading = false;
|
||||||
state.data = callsAdapter.addMany(state.data, payload.calls)
|
const calls = payload.calls.map( (call) => ({...call, played: false}));
|
||||||
|
state.data = callsAdapter.addMany(state.data, calls)
|
||||||
if (state.data && (state.data.ids.length > 0)) {
|
if (state.data && (state.data.ids.length > 0)) {
|
||||||
const first = state.data.ids[0]
|
const first = state.data.ids[0]
|
||||||
const firstTime = state.data.entities[first].time;
|
const firstTime = state.data.entities[first].time;
|
||||||
@@ -250,7 +254,8 @@ export const callsSlice = createSlice({
|
|||||||
},
|
},
|
||||||
[getNewerCalls.fulfilled]: (state, {payload}) => {
|
[getNewerCalls.fulfilled]: (state, {payload}) => {
|
||||||
state.loading = false;
|
state.loading = false;
|
||||||
state.data = callsAdapter.addMany(state.data, payload.calls)
|
const calls = payload.calls.map( (call) => ({...call, played: false}));
|
||||||
|
state.data = callsAdapter.addMany(state.data, calls)
|
||||||
if (state.data && (state.data.ids.length > 0)) {
|
if (state.data && (state.data.ids.length > 0)) {
|
||||||
const first = state.data.ids[0]
|
const first = state.data.ids[0]
|
||||||
const firstTime = state.data.entities[first].time;
|
const firstTime = state.data.entities[first].time;
|
||||||
@@ -268,5 +273,5 @@ export const callsSlice = createSlice({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
export const { addCall } = callsSlice.actions
|
export const { addCall, playedCall } = callsSlice.actions
|
||||||
export const callsReducer = callsSlice.reducer;
|
export const callsReducer = callsSlice.reducer;
|
||||||
|
|||||||
@@ -23,4 +23,10 @@ export const selectActiveSystems = createSelector(
|
|||||||
selectAllSystems,
|
selectAllSystems,
|
||||||
(state) => null,
|
(state) => null,
|
||||||
(systems) => systems.filter(system => system.active === true)
|
(systems) => systems.filter(system => system.active === true)
|
||||||
|
)
|
||||||
|
|
||||||
|
export const selectSystem = createSelector(
|
||||||
|
selectAllSystems,
|
||||||
|
(state) => null,
|
||||||
|
(systems, shortName) => systems.find(system => system.shortName === shortName)
|
||||||
)
|
)
|
||||||
Reference in New Issue
Block a user