From aa4d34303974a79e59e111494bbe5463a298c35a Mon Sep 17 00:00:00 2001 From: Luke Berndt Date: Mon, 23 Jan 2023 22:12:54 -0500 Subject: [PATCH] I think it is ready... --- backend/controllers/calls.js | 6 +-- backend/index.js | 5 +- frontend/src/Call/components/CallItem.js | 12 ++--- frontend/src/Call/components/ListCalls.js | 9 ++-- .../src/Call/components/PlaylistBuilder.js | 30 +++++++---- frontend/src/Event/EventCallInfo.js | 4 -- frontend/src/Event/EventCallItem.js | 52 +++++++++++++++++++ frontend/src/Event/ListEventCalls.js | 8 +-- frontend/src/Event/ViewEvent.js | 19 ++++--- frontend/src/features/call/callSlice.js | 0 frontend/src/features/calls/callsSlice.js | 6 +-- 11 files changed, 108 insertions(+), 43 deletions(-) create mode 100644 frontend/src/Event/EventCallItem.js delete mode 100644 frontend/src/features/call/callSlice.js diff --git a/backend/controllers/calls.js b/backend/controllers/calls.js index 882c1a3..0eccd5c 100644 --- a/backend/controllers/calls.js +++ b/backend/controllers/calls.js @@ -17,7 +17,6 @@ function get_calls(query, numResults, res) { var fields = { _id: true, talkgroupNum: true, - shortName: true, path: true, name: true, time: true, @@ -39,7 +38,6 @@ function get_calls(query, numResults, res) { if (item) { call = { _id: item._id.toHexString(), - shortName: item.shortName, talkgroupNum: item.talkgroupNum, url: item.url, filename: item.path + item.name, @@ -248,7 +246,7 @@ exports.remove_star = function(req, res, next) { try { var o_id = ObjectID.createFromHexString(objectId); } catch (err) { - console.warn("[" + req.params.shortName + "] Error - /:shortName/call/:id generating ObjectID " + err); + console.warn("[" + req.params.shortName + "] Error - /remove_star/:id generating ObjectID " + err); res.status(500); res.send(JSON.stringify({ success: false, @@ -283,7 +281,7 @@ exports.add_star = function(req, res, next) { try { var o_id = ObjectID.createFromHexString(objectId); } catch (err) { - console.warn("[" + req.params.shortName + "] Error - /:shortName/call/:id generating ObjectID " + err); + console.warn("[" + req.params.shortName + "] Error - /add_star/:id generating ObjectID " + err); res.status(500); res.send(JSON.stringify({ success: false, diff --git a/backend/index.js b/backend/index.js index 26f2b42..d17f006 100644 --- a/backend/index.js +++ b/backend/index.js @@ -171,6 +171,8 @@ function addSystemClients(req, res, next) { /*------ CALLS ----------*/ app.get('/card/:id', calls.get_card); +app.post('/add_star/:id', calls.add_star); +app.post('/remove_star/:id', calls.remove_star); app.get('/:shortName/call/:id', calls.get_call); app.get('/:shortName/calls/latest', calls.get_latest_calls); app.get('/:shortName/calls/next', calls.get_next_calls); @@ -178,8 +180,7 @@ app.get('/:shortName/calls/newer', calls.get_newer_calls); app.get('/:shortName/calls/older', calls.get_older_calls); app.get('/:shortName/calls/:time/older', calls.get_iphone_calls); app.get('/:shortName/calls', calls.get_calls); -app.post('/:shortName/star/:id', calls.add_star); -app.post('/:shortName/removeStar/:id', calls.remove_star); + /*------ UPLOADS ---------- upload.single('call'), uploads.upload,*/ app.post('/:shortName/upload', upload.single('call'), uploads.upload, async function (req, res) { diff --git a/frontend/src/Call/components/CallItem.js b/frontend/src/Call/components/CallItem.js index 4e7e269..93ef21a 100644 --- a/frontend/src/Call/components/CallItem.js +++ b/frontend/src/Call/components/CallItem.js @@ -7,15 +7,17 @@ import { import { addStar, removeStar } from "../../features/calls/callsSlice"; -import { useGetTalkgroupsQuery } from '../../features/api/apiSlice' + import { useDispatch } from 'react-redux' const CallItem = (props) => { const call = props.call; + const shortName = props.shortName; + const talkgroups = props.talkgroups; const activeCall = props.activeCall; const [starVisible, setStarVisible] = useState(false); const [starClicked, setStarClicked] = useState(false); - const { data: talkgroupsData, isSuccess: isTalkgroupsSuccess } = useGetTalkgroupsQuery(call.shortName); + const dispatch = useDispatch(); const time = new Date(call.time); @@ -82,10 +84,10 @@ const CallItem = (props) => { } } let talkgroup; - if ((typeof talkgroupsData == 'undefined') || (typeof talkgroupsData.talkgroups[call.talkgroupNum] == 'undefined')) { + if ((typeof talkgroups== 'undefined') || (typeof talkgroups.talkgroups[call.talkgroupNum] == 'undefined')) { talkgroup = call.talkgroupNum; } else { - talkgroup = talkgroupsData.talkgroups[call.talkgroupNum].description; + talkgroup = talkgroups.talkgroups[call.talkgroupNum].description; } return ( props.onClick({ call: call }, e)} {...rowSelected} onDragStart={onDragStart} data-callid={call._id}> @@ -94,8 +96,6 @@ const CallItem = (props) => { {time.toLocaleTimeString()} setStarVisible(true)} onMouseLeave={() => setStarVisible(false)} onClick={handleStarClicked}>{starButton} - - ); } diff --git a/frontend/src/Call/components/ListCalls.js b/frontend/src/Call/components/ListCalls.js index 09d041a..262c7da 100644 --- a/frontend/src/Call/components/ListCalls.js +++ b/frontend/src/Call/components/ListCalls.js @@ -1,4 +1,5 @@ import React, { useEffect, useRef } from "react"; +import { useParams } from 'react-router-dom'; import CallItem from "./CallItem"; import { Icon, @@ -6,11 +7,13 @@ import { Ref } from "semantic-ui-react"; import "../CallPlayer.css"; +import { useGetTalkgroupsQuery } from '../../features/api/apiSlice' // ---------------------------------------------------- const ListCalls = (props) => { const activeCallRef = useRef(); - + const { shortName } = useParams(); + const { data: talkgroupsData, isSuccess: isTalkgroupsSuccess } = useGetTalkgroupsQuery(shortName); //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 @@ -40,9 +43,9 @@ const ListCalls = (props) => { { props.callsData.ids.map((callId, index) => { if (callId === props.activeCallId) { - return () + return () } else { - return + return } }) diff --git a/frontend/src/Call/components/PlaylistBuilder.js b/frontend/src/Call/components/PlaylistBuilder.js index 176365e..e62e8c9 100644 --- a/frontend/src/Call/components/PlaylistBuilder.js +++ b/frontend/src/Call/components/PlaylistBuilder.js @@ -15,7 +15,8 @@ import { Modal, Button, Image, - Form + Form, + Message } from "semantic-ui-react"; import { useAddNewEventMutation, useGetTalkgroupsQuery } from '../../features/api/apiSlice' @@ -113,6 +114,16 @@ function PlaylistBuilder(props) { setDescription("") setPlaylist([]) } + + let content = (
Drag Calls Here
) + if (playlist.length > 0) { + content = ( + + {listItems} + +
) + } + return ( <> 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
+ - -
@@ -158,11 +172,7 @@ function PlaylistBuilder(props) {
- - - {listItems} - -
+ {content}
setPlaylist([])}>Clear diff --git a/frontend/src/Event/EventCallInfo.js b/frontend/src/Event/EventCallInfo.js index 7be07c9..4b75c6b 100644 --- a/frontend/src/Event/EventCallInfo.js +++ b/frontend/src/Event/EventCallInfo.js @@ -13,10 +13,6 @@ import { import CallInfoPane from "../Call/components/CallInfoPane" // ---------------------------------------------------- function EventCallInfo(props) { - - - - return ( diff --git a/frontend/src/Event/EventCallItem.js b/frontend/src/Event/EventCallItem.js new file mode 100644 index 0000000..222f707 --- /dev/null +++ b/frontend/src/Event/EventCallItem.js @@ -0,0 +1,52 @@ +import React, { useState } from "react"; +import { + Table, + Icon, + Label +} from "semantic-ui-react"; + +import { useGetTalkgroupsQuery } from '../features/api/apiSlice' + + +const EventCallItem = (props) => { + const call = props.call; + const activeCall = props.activeCall; + const { data: talkgroupsData, isSuccess: isTalkgroupsSuccess } = useGetTalkgroupsQuery(call.shortName); + + + const time = new Date(call.time); + + + + let rowSelected = {}; + + + + + + + if (activeCall) { + rowSelected = { + positive: true, + color: "blue", + key: "blue", + inverted: "true" + } + } + let talkgroup; + if ((typeof talkgroupsData == 'undefined') || (typeof talkgroupsData.talkgroups[call.talkgroupNum] == 'undefined')) { + talkgroup = call.talkgroupNum; + } else { + talkgroup = talkgroupsData.talkgroups[call.talkgroupNum].description; + } + return ( + props.onClick({ call: call }, e)} {...rowSelected}> + {call.len} + {talkgroup} + {time.toLocaleTimeString()} + {call.shortName} + + ); +} + +export default EventCallItem; diff --git a/frontend/src/Event/ListEventCalls.js b/frontend/src/Event/ListEventCalls.js index a7b88d1..c0973cc 100644 --- a/frontend/src/Event/ListEventCalls.js +++ b/frontend/src/Event/ListEventCalls.js @@ -1,5 +1,5 @@ import React, { useEffect, useRef } from "react"; -import CallItem from "../Call/components/CallItem"; +import EventCallItem from "./EventCallItem"; import { Icon, Table, @@ -31,7 +31,7 @@ const ListEventCalls = (props) => { Len Talkgroup Time - + System {props.eventData && @@ -39,9 +39,9 @@ const ListEventCalls = (props) => { { props.eventData.calls.map((call, index) => { if (call._id === props.activeCallId) { - return () + return () } else { - return + return } }) diff --git a/frontend/src/Event/ViewEvent.js b/frontend/src/Event/ViewEvent.js index 97646e0..f87d31f 100644 --- a/frontend/src/Event/ViewEvent.js +++ b/frontend/src/Event/ViewEvent.js @@ -68,21 +68,23 @@ function ViewEvent(props) { const dateRange = (start, end) => { if (start.getYear() != end.getYear()) { - return {"part1": start.toLocaleDateString('en-us', { weekday:"short", year:"numeric", month:"short", day:"numeric"}) + " " + start.toLocaleTimeString(), "part2": end.toLocaleDateString('en-us', { weekday:"short", year:"numeric", month:"short", day:"numeric"}) + " " + end.toLocaleTimeString()}; + return {"part1": start.toLocaleDateString('en-us', { weekday:"short", year:"numeric", month:"short", day:"numeric"}) + " " + start.toLocaleTimeString([], {hour: 'numeric', minute:'2-digit'}), "part2": end.toLocaleDateString('en-us', { weekday:"short", year:"numeric", month:"short", day:"numeric"}) + " " + end.toLocaleTimeString([], {hour: 'numeric', minute:'2-digit'})}; } else if (start.getMonth() != end.getMonth()) { - return {"part1": start.toLocaleDateString('en-us', { weekday:"short", month:"short", day:"numeric"}) + " " + start.toLocaleTimeString(), "part2": end.toLocaleDateString('en-us', { weekday:"short", month:"short", day:"numeric"}) + " " + end.toLocaleTimeString()}; + return {"part1": start.toLocaleDateString('en-us', { weekday:"short", month:"short", day:"numeric"}) + " " + start.toLocaleTimeString([], {hour: 'numeric', minute:'2-digit'}), "part2": end.toLocaleDateString('en-us', { weekday:"short", month:"short", day:"numeric"}) + " " + end.toLocaleTimeString([], {hour: 'numeric', minute:'2-digit'})}; } else if (start.getDay() != end.getDay()) { - return {"part1": start.toLocaleDateString('en-us', { weekday:"short", month:"short", day:"numeric"}) + " " + start.toLocaleTimeString(), "part2": end.toLocaleDateString('en-us', { weekday:"short", day:"numeric"}) + " " + end.toLocaleTimeString()}; + return {"part1": start.toLocaleDateString('en-us', { weekday:"short", month:"short", day:"numeric"}) + " " + start.toLocaleTimeString([], {hour: 'numeric', minute:'2-digit'}), "part2": end.toLocaleDateString('en-us', { weekday:"short", day:"numeric"}) + " " + end.toLocaleTimeString([], {hour: 'numeric', minute:'2-digit'})}; } else { - return {"part1": start.toLocaleDateString('en-us', { weekday:"short", month:"short", day:"numeric"}) + " " + start.toLocaleTimeString(), "part2": end.toLocaleTimeString()}; + return {"part1": start.toLocaleDateString('en-us', { weekday:"short", month:"short", day:"numeric"}) + " " + start.toLocaleTimeString([], {hour: 'numeric', minute:'2-digit'}), "part2": end.toLocaleTimeString([], {hour: 'numeric', minute:'2-digit'})}; } } let dates = {part1: "", part2: ""} + let expirationDate = "" if (eventData) { dates = dateRange(new Date(eventData.startTime),new Date(eventData.endTime)) + expirationDate = new Date(eventData.expireTime).toLocaleDateString('en-us', { weekday:"short", month:"short", day:"numeric"}) } /* const dateRange = (start, end) => { @@ -126,11 +128,16 @@ function ViewEvent(props) { - {eventData && eventData.description} + {eventData&& + <> +

{eventData.description}

+
Expires {expirationDate}
+ + }
-
{dates.part1} →
{dates.part2}
+
{dates.part1}
→ {dates.part2}
diff --git a/frontend/src/features/call/callSlice.js b/frontend/src/features/call/callSlice.js deleted file mode 100644 index e69de29..0000000 diff --git a/frontend/src/features/calls/callsSlice.js b/frontend/src/features/calls/callsSlice.js index a0c5b87..4ef81ea 100644 --- a/frontend/src/features/calls/callsSlice.js +++ b/frontend/src/features/calls/callsSlice.js @@ -129,8 +129,7 @@ const initialState = { export const addStar = createAsyncThunk( 'calls/addStar', async(callId,{getState, requestIdleCallback}) => { - const {shortName} = getState().callPlayer; - const url = process.env.REACT_APP_BACKEND_SERVER + "/" + shortName.toLowerCase() + "/star/" + callId + const url = process.env.REACT_APP_BACKEND_SERVER + "/add_star/" + callId const res = await fetch(url, { method: 'POST', headers: { @@ -148,8 +147,7 @@ export const addStar = createAsyncThunk( export const removeStar = createAsyncThunk( 'calls/removeStar', async(callId,{getState, requestIdleCallback}) => { - const {shortName} = getState().callPlayer; - const url = process.env.REACT_APP_BACKEND_SERVER + "/" + shortName.toLowerCase() + "/removeStar/" + callId + const url = process.env.REACT_APP_BACKEND_SERVER + "/remove_star/" + callId const res = await fetch(url, { method: 'POST', headers: {