diff --git a/frontend/src/Call/CallPlayer.js b/frontend/src/Call/CallPlayer.js
index b85e61e..7ea7721 100644
--- a/frontend/src/Call/CallPlayer.js
+++ b/frontend/src/Call/CallPlayer.js
@@ -4,9 +4,9 @@ import MediaPlayer from "./components/MediaPlayer";
import SupportModal from "./components/SupportModal";
import CallInfo from "./components/CallInfo";
import ListCalls from "./components/ListCalls";
-import { useDispatch } from 'react-redux'
+import { useSelector, useDispatch } from 'react-redux'
import { getOlderCalls, getNewerCalls } from "../features/calls/callsSlice";
-import { useGetGroupsQuery, useGetTalkgroupsQuery } from '../features/api/apiSlice'
+import { useGetTalkgroupsQuery } from '../features/api/apiSlice'
import { useInView } from 'react-intersection-observer';
import {
Container,
@@ -32,7 +32,6 @@ function CallPlayer(props) {
const { shortName } = useParams();
const selectCallId = props.selectCallId;
const callsData = props.callsData;
-
const { ref: loadOlderRef, inView: loadOlderInView } = useInView({
/* Optional options */
threshold: 0.5
@@ -53,6 +52,7 @@ function CallPlayer(props) {
const stickyRef = useRef(); // lets us get the Y Scroll offset for the Call List
const positionRef = useRef(); // lets us get the Y Scroll offset for the Call List
const shouldPlayAddCallRef = useRef(); // we need to do this to make the current value of isPlaying available in the socket message callback
+ const live = useSelector((state) => state.callPlayer.live);
shouldPlayAddCallRef.current = (!isPlaying && autoPlay)?true:false;
let currentCallId = false;
@@ -92,7 +92,7 @@ function CallPlayer(props) {
}
useEffect(() => {
- if (loadNewerInView && callsData && (callsData.ids.length > 0)) {
+ if (loadNewerInView && !live && callsData && (callsData.ids.length > 0)) {
dispatch(getNewerCalls({}));
}
}, [loadNewerInView]);
diff --git a/frontend/src/Call/Calls.js b/frontend/src/Call/Calls.js
index 1a5b35a..84b7870 100644
--- a/frontend/src/Call/Calls.js
+++ b/frontend/src/Call/Calls.js
@@ -5,7 +5,7 @@ import GroupModal from "./components/GroupModal";
import CalendarModal from "./components/CalendarModal";
import CallPlayer from "./CallPlayer";
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 } from "../features/calls/callsSlice";
import { useGetGroupsQuery, useGetTalkgroupsQuery } from '../features/api/apiSlice'
@@ -52,7 +52,7 @@ function Calls(props) {
const positionRef = useRef(); // lets us get the Y Scroll offset for the Call List
const pageYOffset = useRef(); // Store the current Scroll Offset in a way that guarantees the latest value is available when Call Data is updated
const shouldPlayAddCallRef = useRef(); // we need to do this to make the current value of isPlaying available in the socket message callback
- shouldPlayAddCallRef.current = (!isPlaying && autoPlay)?true:false;
+ shouldPlayAddCallRef.current = (!isPlaying && autoPlay) ? true : false;
const filterType = useSelector((state) => state.callPlayer.filterType);
const filterGroupId = useSelector((state) => state.callPlayer.filterGroupId);
@@ -106,8 +106,9 @@ function Calls(props) {
switch (message.type) {
case 'calls':
- pageYOffset.current = positionRef.current.clientHeight;
-
+ if (positionRef.current) {
+ pageYOffset.current = positionRef.current.clientHeight;
+ }
setSelectCallId(message._id);
dispatch(addCall(message));
@@ -273,7 +274,7 @@ function Calls(props) {
}
})
- socket.on("new message", handleSocketMessage );
+ socket.on("new message", handleSocketMessage);
return () => {
socket.off('connect');
@@ -295,15 +296,18 @@ function Calls(props) {
updateUri();
}, [filterGroupId, filterTalkgroups, filterType, filterDate, filterStarred, selectCallId])
-
useEffect(() => {
if (!urlOptions && groupsData && (groupsData.length > 0)) {
setGroupVisible(true);
}
}, [groupsData])
- useLayoutEffect( () => {
- const scrollAmount = parseInt(positionRef.current.clientHeight) - parseInt(pageYOffset.current);
+ useEffect(() => {
+ pageYOffset.current = positionRef.current.clientHeight;
+ }, [callsData])
+
+ useLayoutEffect(() => {
+ const scrollAmount = parseInt(pageYOffset.current) - parseInt(positionRef.current.clientHeight);
if (scrollAmount > 0) {
window.scrollBy(0, scrollAmount);
}
@@ -376,7 +380,7 @@ function Calls(props) {
-
+
);
}
diff --git a/frontend/src/Call/components/PlaylistBuilder.js b/frontend/src/Call/components/PlaylistBuilder.js
index 9ccce31..14513a1 100644
--- a/frontend/src/Call/components/PlaylistBuilder.js
+++ b/frontend/src/Call/components/PlaylistBuilder.js
@@ -19,6 +19,7 @@ import {
Message
} from "semantic-ui-react";
import { useAddNewEventMutation, useGetTalkgroupsQuery } from '../../features/api/apiSlice'
+import { setPlaylist, addToPlaylist, removeFromPLaylist } from '../../features/callPlayer/callPlayerSlice';
import PlaylistItem from "./PlaylistItem"
function PlaylistBuilder(props) {
@@ -26,31 +27,17 @@ function PlaylistBuilder(props) {
const { data: talkgroupsData, isSuccess: isTalkgroupsSuccess } = useGetTalkgroupsQuery(shortName);
const [addNewEvent, { isLoading }] = useAddNewEventMutation()
const { loading: callsLoading, data: callsData } = useSelector((state) => state.calls);
- const [playlist, setPlaylist] = useState([]);
const [open, setOpen] = React.useState(false);
const [title, setTitle] = useState("")
const [description, setDescription] = useState("")
const handleTitleChange = (e, { name, value }) => setTitle(value);
const handleDescriptionChange = (e, { name, value }) => setDescription(value);
+ const playlist = useSelector((state) => state.callPlayer.playlist);
+
+ const dispatch = useDispatch();
- const compareCalls = (a, b) => {
- const aTimestamp = new Date(a.time).getTime()
- const bTimestamp = new Date(b.time).getTime()
- if (aTimestamp > bTimestamp) {
- return -1
- } else {
- return 1
- }
- }
- const addCall = (call) => {
- const found = playlist.find(c => c._id == call._id);
- if (!found) {
- playlist.push(call);
- setPlaylist([...playlist.sort(compareCalls)])
- }
- }
const onDragOver = (event) => {
// It also receives a DragEvent.
@@ -67,6 +54,9 @@ function PlaylistBuilder(props) {
event.preventDefault();
}
+ const removeItem = (call) => {
+ dispatch(removeFromPLaylist(call))
+ }
const onDrop = (event) => {
// Here, we will:
@@ -74,18 +64,10 @@ function PlaylistBuilder(props) {
// - and reset the DnD state
var callId = event.dataTransfer.getData("call-id");
console.log("Dropping: " + callId);
- addCall(callsData.entities[callId])
+ dispatch(addToPlaylist(callsData.entities[callId]))
}
-const removeItem = (call) => {
- if (call) {
- const found = playlist.findIndex(c => c._id == call._id);
- if (found!=-1) {
- playlist.splice(found,1)
- setPlaylist([...playlist.sort(compareCalls)])
- }
- }
-}
+
let listItems = "";
@@ -93,10 +75,12 @@ const removeItem = (call) => {
let tgAlpha = call.talkgroupNum;
if (talkgroupsData) {
const talkgroup = talkgroupsData.talkgroups[call.talkgroupNum]
- tgAlpha = talkgroup.alpha?talkgroup.alpha:tgAlpha;
+ if (talkgroup && talkgroup.alpha!=" ") {
+ tgAlpha = talkgroup.alpha;
+ }
}
- return ( )
+ return ()
})
const submitPlaylist = () => {
@@ -104,81 +88,80 @@ const removeItem = (call) => {
}
const handleSubmit = () => {
- console.log(title)
setOpen(false)
- const callIds = playlist.map( (call) => call._id)
+ const callIds = playlist.map((call) => call._id)
const event = {
title,
description,
callIds
}
- addNewEvent(event)
- setTitle("")
- setDescription("")
- setPlaylist([])
+ addNewEvent(event);
+ setTitle("");
+ setDescription("");
+ dispatch(setPlaylist([]));
}
- let content = ()
+ let content = ()
if (playlist.length > 0) {
content = ()
+
+ {listItems}
+
+ )
}
return (
<>
- setOpen(false)}
- onOpen={() => setOpen(true)}
- open={open}
- >
- Submit an Event
-
-
-
-
-
- The Events feature is a work in progress! Things may break, change, or get deleted. Contact me with ideas or problems: luke@robotastic.com
+ setOpen(false)}
+ onOpen={() => setOpen(true)}
+ open={open}
+ >
+ Submit an Event
+
+
+
+
+
+ The Events feature is a work in progress! Things may break, change, or get deleted. Contact me with ideas or problems: luke@robotastic.com
-
- Event
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
{content}
>
diff --git a/frontend/src/features/callPlayer/callPlayerSlice.js b/frontend/src/features/callPlayer/callPlayerSlice.js
index 3abd213..64f4090 100644
--- a/frontend/src/features/callPlayer/callPlayerSlice.js
+++ b/frontend/src/features/callPlayer/callPlayerSlice.js
@@ -17,6 +17,16 @@ const initialState = {
live: false
}
+const compareCalls = (a, b) => {
+ const aTimestamp = new Date(a.time).getTime()
+ const bTimestamp = new Date(b.time).getTime()
+ if (aTimestamp > bTimestamp) {
+ return -1
+ } else {
+ return 1
+ }
+}
+
export const callPlayerSlice = createSlice({
name: 'callPlayer',
initialState,
@@ -33,6 +43,23 @@ export const callPlayerSlice = createSlice({
state.playlist = action.payload;
}
},
+ removeFromPlaylist: (state, action) => {
+ const call = action.payload;
+ if (call) {
+ const found = state.playlist.findIndex(c => c._id == call._id);
+ if (found != -1) {
+ state.playlist = state.playlist.splice(found, 1)
+ }
+ }
+ },
+ addToPlaylist: (state, action) => {
+ const call = action.payload;
+ const found = state.playlist.find(c => c._id == call._id);
+ if (!found) {
+ const newlist = [...state.playlist, call];
+ state.playlist = newlist.sort(compareCalls);
+ }
+ },
setFilter: (state,action) => {
var filter={};
state.live = !action.payload.live ? state.live : action.payload.live;
@@ -75,7 +102,7 @@ export const callPlayerSlice = createSlice({
})
// Action creators are generated for each case reducer function
-export const { setCurrentCallId, setCallTime, setFilter, setLive, setShortName, setDateFilter, setStarredFilter, setAllFilter, setGroupFilter, setTalkgroupFilter } = callPlayerSlice.actions
+export const { setCurrentCallId, setCallTime, setFilter, setLive, setPlaylist, removeFromPLaylist, addToPlaylist, setShortName, setDateFilter, setStarredFilter, setAllFilter, setGroupFilter, setTalkgroupFilter } = callPlayerSlice.actions
export default callPlayerSlice.reducer