it works - the group stuff!

This commit is contained in:
Luke Berndt
2023-03-18 12:46:31 -04:00
parent 5bfff7bb90
commit 8f7f4fae37
7 changed files with 400 additions and 388 deletions

View File

@@ -41,7 +41,7 @@ exports.getGroups = async function (req, res, next) {
return; return;
} }
} else { } else {
const group = await Group.findOne( const group = await Group.find(
{ {
shortName: req.params.shortName.toLowerCase() shortName: req.params.shortName.toLowerCase()
}).sort("position").exec(); }).sort("position").exec();
@@ -63,57 +63,56 @@ exports.getGroups = async function (req, res, next) {
); );
}; };
exports.deleteGroup = function (req, res, next) { exports.deleteGroup = async function (req, res, next) {
//router.get('/system/:shortName/remove_group/:groupId', isLoggedIn, function(req, res) { const system = await System.findOne({ 'shortName': req.params.shortName.toLowerCase() }).catch(err => {
System.findOne({
'shortName': req.params.shortName.toLowerCase()
}, function (err, system) {
if (err) {
console.error(err);
res.json({ success: false, message: err });
return;
}
if (!system) {
console.error(err);
res.json({
success: false,
message: "That Short Name does not exist."
});
return;
}
if (!system.userId.equals(req.user._id)) {
res.json({
success: false,
message: "You are not the user associated with this system."
});
return;
}
Group.findOneAndRemove({
shortName: req.params.shortName.toLowerCase(),
'_id': new mongoose.Types.ObjectId(req.params.groupId)
}, function (err) {
if (err) {
res.json({
success: false,
message: err
});
return;
} else {
res.json({
success: true
});
return;
}
// removed!
});
console.error(err);
res.status(500);
res.json({ success: false, message: err });
return;
});
if (!system) {
console.error(err);
res.status(404);
res.json({
success: false,
message: "That Short Name does not exist."
});
return;
}
if (!system.userId.equals(req.user._id)) {
res.status(401);
res.json({
success: false,
message: "You are not the user associated with this system."
});
return;
}
await Group.findOneAndRemove({
shortName: req.params.shortName.toLowerCase(),
'_id': new mongoose.Types.ObjectId(req.params.groupId)
}).catch(err => {
res.status(500);
res.json({
success: false,
message: err
});
return;
}); });
};
exports.reorderGroups = function (req, res, next) {
res.json({
success: true
});
return;
}
exports.reorderGroups = function (req, res, next) {
console.log(req.body)
//router.post('/system/:shortName/group_order', isLoggedIn, function(req, res) { //router.post('/system/:shortName/group_order', isLoggedIn, function(req, res) {
process.nextTick(async function () { process.nextTick(async function () {
const system = await System.findOne({ shortName: req.params.shortName.toLowerCase() }); const system = await System.findOne({ shortName: req.params.shortName.toLowerCase() });
if (!system) { if (!system) {
@@ -132,7 +131,15 @@ exports.reorderGroups = function (req, res, next) {
}); });
return; return;
} }
console.log(req.body)
if (!req.body.groupOrder) {
res.status(500);
res.json({
success: false,
message: "Order data is wrong."
});
return;
}
var groupOrder = JSON.parse(req.body.groupOrder); var groupOrder = JSON.parse(req.body.groupOrder);
for (var i = 0; i < groupOrder.length; i++) { for (var i = 0; i < groupOrder.length; i++) {
@@ -166,14 +173,15 @@ exports.reorderGroups = function (req, res, next) {
res.json({ res.json({
success: true success: true
}); });
} });
);
}; };
exports.upsertGroup = function (req, res, next) { exports.upsertGroup = function (req, res, next) {
console.log(req.body)
//router.post('/system/:shortName/group/:groupId?', isLoggedIn, function(req, res) { //router.post('/system/:shortName/group/:groupId?', isLoggedIn, function(req, res) {
process.nextTick(async function () { process.nextTick(async function () {
let system = System.findOne({ shortName: req.params.shortName.toLowerCase() }); console.log(req.body)
let system = await System.findOne({ shortName: req.params.shortName.toLowerCase() });
if (!system) { if (!system) {
res.status(404); res.status(404);
@@ -213,7 +221,7 @@ exports.upsertGroup = function (req, res, next) {
var groupId = req.params.groupId; var groupId = req.params.groupId;
let group = Group.findOneAndUpdate( let group = await Group.findOneAndUpdate(
{ {
_id: new mongoose.Types.ObjectId(groupId), _id: new mongoose.Types.ObjectId(groupId),
shortName: req.params.shortName.toLowerCase() shortName: req.params.shortName.toLowerCase()
@@ -225,20 +233,17 @@ exports.upsertGroup = function (req, res, next) {
{ {
new: true, new: true,
upsert: true upsert: true
}).catch(err => {
res.status(500);
res.json({
success: false,
message: err
});
return;
}); });
res.json(group);
return;
if (!group) {
res.status(500);
res.json({
success: false,
message: err
});
return;
} else {
res.json(group);
return;
}
} }
); );
} }

View File

@@ -128,6 +128,7 @@ function isAdmin(req, res, next) {
} }
function isLoggedIn(req, res, next) { function isLoggedIn(req, res, next) {
console.log(req.body);
if (req.isAuthenticated()) return next(); if (req.isAuthenticated()) return next();
res.status(401).send({ res.status(401).send({
success: false, success: false,

View File

@@ -1,4 +1,6 @@
import React, { Component } from "react"; import React, { useEffect, useLayoutEffect, useState, useRef, useCallback, useMemo } from "react";
import { useGetSystemsQuery, useGetTalkgroupsQuery, useGetGroupsQuery, useUpdateGroupMutation, useCreateGroupMutation, useDeleteGroupMutation, useSaveGroupOrderMutation} from '../features/api/apiSlice'
import { import {
Grid, Grid,
Modal, Modal,
@@ -13,84 +15,81 @@ import {
// ---------------------------------------------------- // ----------------------------------------------------
class GroupModal extends Component { const GroupModal = (props) => {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleClose = this.handleClose.bind(this);
// Set initial state const emptyGroup = {
this.state = { name: "",
editGroup: false, items: []
groupName: "",
group: {
name: "",
items: []
},
talkgroups: this.props.talkgroups ? this.props.talkgroups : []
};
} }
const [editGroup, setEditGroup] = useState(false);
const [groupName, setGroupName] = useState("");
const [group, setGroup] = useState(emptyGroup)
const [talkgroups, setTalkgroups] = useState(props.talkgroups ? props.talkgroups : [])
componentDidMount() { const { data: talkgroupsData, isSuccess: isTalkgroupsSuccess } = useGetTalkgroupsQuery(props.shortName);
//this.props.groupActions.fetchGroups(this.props.shortName); const { data: groupsData, isSuccess: isGroupsSuccess } = useGetGroupsQuery(props.shortName);
const [ updateGroup,{ isLoading: isUpdating } ] = useUpdateGroupMutation();
const [ createGroup,{ isLoading: isCreating } ] = useCreateGroupMutation();
this.props.talkgroupActions.fetchTalkgroups(this.props.shortName); useEffect(() => {
} if (talkgroupsData && groupsData && props.editGroupId) {
let editGroup = groupsData.find(
group => group._id === props.editGroupId
);
let items = [];
componentDidUpdate(prevProps) { let talkgroups = talkgroupsData.slice(0); //copy
for (var i = 0; i < editGroup.talkgroups.length; i++) {
// This determines if you are trying to edit a group. const talkgroupNum = editGroup.talkgroups[i];
// In this case, the value of editGroupID will chane to the group being edited const index = talkgroups.findIndex(tg => tg.num === talkgroupNum);
if (this.props.talkgroups && this.props.groups && this.props.editGroupId && !prevProps.editGroupId) { if (index >= 0) {
var editGroup = this.props.groups.find( const item = {
group => group._id === this.props.editGroupId num: talkgroups[index].num,
); description: talkgroups[index].description
var items = []; };
items.push(item);
var talkgroups = this.props.talkgroups; talkgroups = talkgroups
for (var i = 0; i < editGroup.talkgroups.length; i++) { .slice(0, index)
const talkgroupId = editGroup.talkgroups[i]; .concat(talkgroups.slice(index + 1));
const index = talkgroups.findIndex(tg => tg.num === talkgroupId);
if (index >= 0) {
const item = {
num: talkgroups[index].num,
description: talkgroups[index].description
};
items.push(item);
talkgroups = talkgroups
.slice(0, index)
.concat(talkgroups.slice(index + 1));
}
} }
// we want to remove that are part of the Group from the list on the Left
const group = { name: editGroup.groupName, items: items }
this.setState({ group: group, talkgroups: talkgroups, groupName: editGroup.groupName });
} }
// we want to remove that are part of the Group from the list on the Left
if (this.props.talkgroups && !prevProps.talkgroups) { const group = { name: editGroup.groupName, items: items }
// If we are not editing, make sure there is the full list on the left. setGroup(group);
this.setState({ talkgroups: [...this.props.talkgroups] }) setTalkgroups(talkgroups);
setGroupName(editGroup.groupName);
} }
},[groupsData,talkgroupsData, props.editGroupId]);
// If we are done editing, clear out the modal
if (!this.props.editGroupId && (this.props.editGroupId !== prevProps.editGroupId)) { useEffect(() => {
this.setState({ if (!props.editGroupId && talkgroupsData) {
groupName: "", group: { setTalkgroups([...talkgroupsData]);
name: "",
items: []
},
talkgroups: [...this.props.talkgroups]
});
} }
} },[talkgroupsData]);
removeTalkgroup(event, index) {
useEffect(() => {
if (!props.editGroupId && props.talkgroups) {
setGroupName("");
setGroup(emptyGroup);
setTalkgroups( [...props.talkgroups]);
}
},[props.editGroupId]);
const removeTalkgroup = (event, index) => {
const item = { const item = {
num: this.state.group.items[index].num, num: group.items[index].num,
description: this.state.group.items[index].description description: group.items[index].description
}; };
const talkgroups = this.state.talkgroups.slice(0); // copy let talkgroups = talkgroupsData.slice(0); // copy
for (var i = 0, len = talkgroups.length; i < len; i++) { for (var i = 0, len = talkgroups.length; i < len; i++) {
if (item.num < talkgroups[i].num) { if (item.num < talkgroups[i].num) {
@@ -98,110 +97,76 @@ class GroupModal extends Component {
break; break;
} }
} }
this.setState({ setGroup( {
group: { items: this.state.group.items
items: this.state.group.items .slice(0, index)
.slice(0, index) .concat(this.state.group.items.slice(index + 1))
.concat(this.state.group.items.slice(index + 1))
},
talkgroups: talkgroups
}); });
setTalkgroups(talkgroups);
} }
handleInputChange = (e, { name, value }) => this.setState({ [name]: value }); const handleInputChange = (e, { name, value }) => this.setState({ [name]: value });
addTalkgroup(event, index) { const addTalkgroup = (event, index) => {
const item = { const item = {
num: this.state.talkgroups[index].num, num: talkgroupsData[index].num,
description: this.state.talkgroups[index].description description: talkgroupsData[index].description
}; };
this.setState({ setGroup({ items: group.items.concat(item) })
group: { items: this.state.group.items.concat(item) }, setTalkgroups(talkgroups.slice(0, index).concat(talkgroups.slice(index + 1)));
talkgroups: this.state.talkgroups
.slice(0, index)
.concat(this.state.talkgroups.slice(index + 1))
});
} }
handleClose = () => {
this.setState({
groupName: "", group: {
name: "",
items: []
},
talkgroups: [...this.props.talkgroups]
});
this.props.onClose(false);
}
handleSubmit() {
var talkgroupNums = this.state.group.items.map(a => a.num);
if (this.props.editGroupId) { const handleClose = () => {
setGroupName("");
setGroup(emptyGroup);
setTalkgroups([...talkgroupsData]);
props.onClose();
}
const handleSubmit = async () => {
const talkgroupNums = group.items.map(a => a.num);
if (props.editGroupId) {
const data = { const data = {
_id: this.props.editGroupId, _id: props.editGroupId,
shortName: this.props.shortName, shortName: props.shortName,
groupName: this.state.groupName, groupName: groupName,
talkgroups: JSON.stringify(talkgroupNums) talkgroups: JSON.stringify(talkgroupNums)
}; };
this.setState({ setGroupName("");
groupName: "", group: { setGroup(emptyGroup);
name: "", setTalkgroups([...talkgroupsData]);
items: [] await updateGroup(data);
}, props.onClose(true);
talkgroups: [...this.props.talkgroups]
});
this.props.groupActions.updateGroup(data).then(requestMessage => {
if (requestMessage) {
// report to the user is there was a problem during registration
this.setState({
requestMessage
});
this.props.onClose(false);
} else {
this.props.onClose(true);
}
});
} else { } else {
const data = { const data = {
shortName: this.props.shortName, shortName: props.shortName,
groupName: this.state.groupName, groupName: groupName,
talkgroups: JSON.stringify(talkgroupNums) talkgroups: JSON.stringify(talkgroupNums)
}; };
this.setState({ setGroupName("");
groupName: "", group: { setGroup(emptyGroup);
name: "", setTalkgroups([...talkgroupsData]);
items: []
}, await createGroup(data);
talkgroups: [...this.props.talkgroups] props.onClose();
});
this.props.groupActions.createGroup(data).then(requestMessage => {
if (requestMessage) {
// report to the user is there was a problem during registration
this.setState({
requestMessage
});
this.props.onClose(false);
} else {
this.props.onClose(true);
}
});
} }
} }
render() {
const talkgroups = this.state.talkgroups;
const group = this.state.group.items;
const railStyle = { const railStyle = {
top: "15px", top: "15px",
minHeight: "200px" minHeight: "200px"
}; };
return ( return (
<Modal open={this.props.open} onClose={this.handleClose} centered={false}> <Modal open={props.open} onClose={handleClose} centered={false}>
<Modal.Header> <Modal.Header>
{this.props.editGroupId ? "Edit Group" : "Create Group"} {props.editGroupId ? "Edit Group" : "Create Group"}
</Modal.Header> </Modal.Header>
<Modal.Content scrolling> <Modal.Content scrolling>
<Modal.Description> <Modal.Description>
@@ -227,7 +192,7 @@ class GroupModal extends Component {
<Icon <Icon
link link
name="plus" name="plus"
onClick={e => this.addTalkgroup(e, i)} onClick={e => addTalkgroup(e, i)}
/> />
</Table.Cell> </Table.Cell>
</Table.Row> </Table.Row>
@@ -238,26 +203,26 @@ class GroupModal extends Component {
<Segment style={railStyle}> <Segment style={railStyle}>
<Input <Input
name="groupName" name="groupName"
onChange={this.handleInputChange} onChange={e => setGroupName(e.target.value)}
placeholder="Group Name" placeholder="Group Name"
value={this.state.groupName} value={groupName}
/> />
<List divided relaxed> <List divided relaxed>
{group.map((talkgroup, i) => ( {group.items.map((talkgroup, i) => (
<List.Item key={"Group-" + i}> <List.Item key={"Group-" + i}>
<List.Icon <List.Icon
name="remove" name="remove"
verticalAlign="middle" verticalAlign="middle"
link={true} link={true}
onClick={e => this.removeTalkgroup(e, i)} onClick={e => removeTalkgroup(e, i)}
/> />
<List.Content>{talkgroup.description}</List.Content> <List.Content>{talkgroup.description}</List.Content>
</List.Item> </List.Item>
))} ))}
</List> </List>
<Button onClick={this.handleSubmit}> <Button onClick={handleSubmit}>
<Icon name="checkmark" />{" "} <Icon name="checkmark" />{" "}
{this.props.editGroupId ? "Update" : "Save"} {props.editGroupId ? "Update" : "Save"}
</Button> </Button>
</Segment> </Segment>
</Rail> </Rail>
@@ -266,14 +231,13 @@ class GroupModal extends Component {
</Modal.Description> </Modal.Description>
</Modal.Content> </Modal.Content>
<Modal.Actions> <Modal.Actions>
<Button onClick={this.handleSubmit}> <Button onClick={handleSubmit}>
<Icon name="checkmark" />{" "} <Icon name="checkmark" />{" "}
{this.props.editGroupId ? "Update" : "Save"} {props.editGroupId ? "Update" : "Save"}
</Button> </Button>
</Modal.Actions> </Modal.Actions>
</Modal> </Modal>
); );
} }
}
export default GroupModal; export default GroupModal;

View File

@@ -19,18 +19,15 @@ import {
// ---------------------------------------------------- // ----------------------------------------------------
class ListGroups extends Component { const ListGroups = (props) => {
constructor(props) {
super(props);
}
//https://stackoverflow.com/questions/36559661/how-can-i-dispatch-from-child-components-in-react-redux //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 //https://stackoverflow.com/questions/42597602/react-onclick-pass-event-with-parameter
render() {
const groups = this.props.groups; const groups = props.groups;
if (groups) { if (groups) {
let groupsDisplay = props.order.map( id => props.groups.find( group => group._id == id ));
return ( return (
<Table > <Table >
@@ -42,7 +39,7 @@ class ListGroups extends Component {
</Table.Row> </Table.Row>
</Table.Header> </Table.Header>
<Table.Body> <Table.Body>
{groups.map((group, i) => ( {groupsDisplay.map((group, i) => (
<Table.Row key={ "Group-" + i}> <Table.Row key={ "Group-" + i}>
<Table.Cell>{group.groupName}</Table.Cell> <Table.Cell>{group.groupName}</Table.Cell>
<Table.Cell>{group.talkgroups.length}</Table.Cell> <Table.Cell>{group.talkgroups.length}</Table.Cell>
@@ -50,19 +47,21 @@ class ListGroups extends Component {
<Icon <Icon
name="pencil alternate" name="pencil alternate"
link={true} link={true}
onClick={e => this.props.editGroup(group._id)} onClick={e => props.editGroup(group._id)}
/><Icon /><Icon
name="up arrow" name="up arrow"
link={true} link={i==0?false:true}
onClick={e => this.props.reorderGroup(i, i-1)} disabled={i==0?true:false}
onClick={e => props.reorderGroup(i, i-1)}
/><Icon /><Icon
name="down arrow" name="down arrow"
link={true} link={i==groupsDisplay.length-1?false:true}
onClick={e => this.props.reorderGroup(i, i+1)} disabled={i==groupsDisplay.length-1?true:false}
onClick={e => props.reorderGroup(i, i+1)}
/><Icon /><Icon
name="remove" name="remove"
link={true} link={true}
onClick={e => this.props.deleteGroup(group._id)} onClick={e => props.deleteGroup(group._id)}
/> />
</Table.Cell> </Table.Cell>
</Table.Row> </Table.Row>
@@ -77,6 +76,5 @@ class ListGroups extends Component {
); );
} }
} }
}
export default ListGroups; export default ListGroups;

View File

@@ -10,14 +10,15 @@ import {
} from "semantic-ui-react"; } from "semantic-ui-react";
import { useGetSystemsQuery, } from '../features/api/apiSlice' import { useGetSystemsQuery, } from '../features/api/apiSlice'
import { useDispatch } from 'react-redux' import { useDispatch } from 'react-redux'
import { push } from '@lagunovsky/redux-react-router'
import { useLocation, useNavigate, useParams } from 'react-router-dom';
// ---------------------------------------------------- // ----------------------------------------------------
const ListSystems = (props) => { const ListSystems = (props) => {
const { data, isSuccess } = useGetSystemsQuery(); const { data, isSuccess } = useGetSystemsQuery();
const dispatch = useDispatch(); const dispatch = useDispatch();
const navigate = useNavigate();
let systems = false; let systems = false;
if (isSuccess) { if (isSuccess) {
systems = data.systems; systems = data.systems;
@@ -30,12 +31,13 @@ const ListSystems = (props) => {
<div> <div>
<Container> <Container>
<Header as="h1">Radio Systems</Header> <Header as="h1">Radio Systems</Header>
<Button onClick={(e) => dispatch(push("/create-system"))}><Icon name='plus' />Add System</Button>
<Button onClick={(e) => navigate("/create-system")}><Icon name='plus' />Add System</Button>
<Divider /> <Divider />
<Card.Group itemsPerRow={4}> <Card.Group itemsPerRow={4}>
{systems && {systems &&
systems.map((system) => systems.map((system) =>
<SystemCard system={system} key={system.shortName} onClick={(e) => dispatch(push("/system/" + system.shortName))}/> <SystemCard system={system} key={system.shortName} onClick={(e) => navigate("/system/" + system.shortName)}/>
)} )}
</Card.Group> </Card.Group>
</Container> </Container>

View File

@@ -8,7 +8,7 @@ import UpdatePermissionModal from "../Permission/UpdatePermissionModalContainer.
import AddPermissionModal from "../Permission/AddPermissionModalContainer.js"; import AddPermissionModal from "../Permission/AddPermissionModalContainer.js";
import ErrorChart from "./ResponsiveErrorChart" import ErrorChart from "./ResponsiveErrorChart"
import CallChart from "./ResponsiveCallChart" import CallChart from "./ResponsiveCallChart"
import { useGetSystemsQuery, useGetTalkgroupsQuery, useGetGroupsQuery, useGetErrorsQuery} from '../features/api/apiSlice' import { useGetSystemsQuery, useGetTalkgroupsQuery, useGetGroupsQuery, useGetErrorsQuery, useDeleteGroupMutation, useCreateGroupMutation, useSaveGroupOrderMutation } from '../features/api/apiSlice'
import { import {
Button, Button,
Confirm, Confirm,
@@ -31,6 +31,8 @@ const System = (props) => {
const { data: talkgroupsData, isSuccess: isTalkgroupsSuccess } = useGetTalkgroupsQuery(shortName); const { data: talkgroupsData, isSuccess: isTalkgroupsSuccess } = useGetTalkgroupsQuery(shortName);
const { data: groupsData, isSuccess: isGroupsSuccess } = useGetGroupsQuery(shortName); const { data: groupsData, isSuccess: isGroupsSuccess } = useGetGroupsQuery(shortName);
const { data: errorsData, isSuccess: isErrorsSuccess } = useGetErrorsQuery(shortName); const { data: errorsData, isSuccess: isErrorsSuccess } = useGetErrorsQuery(shortName);
const [deleteGroupAPI, { isLoading: isDeleting }] = useDeleteGroupMutation();
const [reorderGroupsAPI, { isLoading: isReordering }] = useSaveGroupOrderMutation();
const [openSystemDeleteConfirm, setOpenSystemDeleteConfirm] = useState(false); const [openSystemDeleteConfirm, setOpenSystemDeleteConfirm] = useState(false);
const [openPermissionDeleteConfirm, setOpenPermissionDeleteConfirm] = useState(false); const [openPermissionDeleteConfirm, setOpenPermissionDeleteConfirm] = useState(false);
const [openMessage, setOpenMessage] = useState(false); const [openMessage, setOpenMessage] = useState(false);
@@ -39,6 +41,7 @@ const System = (props) => {
const [editGroupId, setEditGroupId] = useState(false); const [editGroupId, setEditGroupId] = useState(false);
const [errorData, setErrorData] = useState({}); const [errorData, setErrorData] = useState({});
const [callData, setCallData] = useState({}); const [callData, setCallData] = useState({});
const [groupOrder, setGroupOrder] = useState([]);
const processErrors = (errors) => { const processErrors = (errors) => {
@@ -149,109 +152,123 @@ const System = (props) => {
} }
} }
*/ */
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 editGroup = (groupId) => {
setEditGroupId(groupId)
setGroupVisible((state) => !state)
}
const handleGroupClose = () => { const deleteGroup = async (groupId) => {
setEditGroupId(false) for (const num in groupsData) {
setGroupVisible(false) if (groupsData[num]._id == groupId) {
await deleteGroupAPI(groupsData[num])
}
} }
}
const handleGroupToggle = () => {
setEditGroupId(false) const reorderGroup = (oldIndex, newIndex) => {
setGroupVisible((state)=> !state) if ((newIndex < 0) || (newIndex > (groupOrder.length - 1))) {
return
} }
const moveOrder = groupOrder.slice();
moveOrder.splice(newIndex, 0, moveOrder.splice(oldIndex, 1)[0]);
setGroupOrder(moveOrder);
const handleExport = () => { }
/* this.props.talkgroupActions
.exportTalkgroups(this.props.system.shortName) const handleGroupClose = () => {
.then(requestMessage => { setEditGroupId(false)
if (requestMessage) { setGroupVisible(false)
// report to the user is there was a problem during registration }
this.setState({ requestMessage });
} const handleGroupToggle = () => {
});*/ setEditGroupId(false)
} setGroupVisible((state) => !state)
}
const saveGroupOrder = () => {
/*const order = this.props.groups.map(x => x._id);
const data = {
groupOrder: JSON.stringify(order) const handleExport = () => {
}; /* this.props.talkgroupActions
this.props.groupActions .exportTalkgroups(this.props.system.shortName)
.saveGroupOrder(this.props.system.shortName, data) .then(requestMessage => {
.then(requestMessage => { if (requestMessage) {
if (requestMessage) { // report to the user is there was a problem during registration
} this.setState({ requestMessage });
});*/ }
} });*/
}
const handleUpload = (file) => { const saveGroupOrder = async () => {
/*this.props.talkgroupActions await reorderGroupsAPI({shortName: shortName, order: {groupOrder: JSON.stringify(groupOrder)}});
.importTalkgroups(this.props.system.shortName, file)
.then(requestMessage => { /*const order = this.props.groups.map(x => x._id);
if (requestMessage) { const data = {
// report to the user is there was a problem during registration groupOrder: JSON.stringify(order)
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); this.props.groupActions
.saveGroupOrder(this.props.system.shortName, data)
.then(requestMessage => {
if (requestMessage) {
}
});*/
}
let system = false; 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) { if (isSystemsSuccess) {
system = systemsData.systems.find(sys=>sys.shortName == shortName); system = systemsData.systems.find(sys => sys.shortName == shortName);
} }
useEffect(() => { useEffect(() => {
if (isSystemsSuccess) { if (groupsData) {
processStatistics(systemsData.stats[shortName]) let newOrder = [];
} groupsData.forEach(group => {
},[isSystemsSuccess]);
newOrder.push(group._id);
});
setGroupOrder(newOrder);
}
}, [groupsData])
useEffect(() => {
if (isSystemsSuccess) {
processStatistics(systemsData.stats[shortName])
}
}, [isSystemsSuccess]);
useEffect(() => { useEffect(() => {
if (isErrorsSuccess) { if (isErrorsSuccess) {
processErrors(errorData) processErrors(errorData)
} }
},[isErrorsSuccess]); }, [isErrorsSuccess]);
let fileInput = null; let fileInput = null;
var location = ""; var location = "";
@@ -266,6 +283,7 @@ const System = (props) => {
<Button onClick={saveGroupOrder} > Save Order</Button> <Button onClick={saveGroupOrder} > Save Order</Button>
<ListGroups <ListGroups
groups={groupsData} groups={groupsData}
order={groupOrder}
reorderGroup={reorderGroup} reorderGroup={reorderGroup}
deleteGroup={deleteGroup} deleteGroup={deleteGroup}
editGroup={editGroup} editGroup={editGroup}
@@ -333,7 +351,7 @@ const System = (props) => {
<Segment clearing={true}> <Segment clearing={true}>
<Button <Button
color="red" color="red"
onClick={ ()=>setOpenSystemDeleteConfirm(true)} onClick={() => setOpenSystemDeleteConfirm(true)}
disabled={!isSystemsSuccess} disabled={!isSystemsSuccess}
content="Delete" content="Delete"
floated="right" floated="right"
@@ -515,7 +533,7 @@ const System = (props) => {
<GroupModal <GroupModal
shortName={system.shortName} shortName={shortName}
editGroupId={editGroupId} editGroupId={editGroupId}
open={groupVisible} open={groupVisible}
onClose={handleGroupClose} onClose={handleGroupClose}
@@ -548,7 +566,7 @@ const System = (props) => {
pointing: true pointing: true
}} }}
panes={panes} panes={panes}
//defaultActiveIndex={activeTab} //defaultActiveIndex={activeTab}
/> />
</Container> </Container>
} }

View File

@@ -1,73 +1,97 @@
// Import the RTK Query methods from the React-specific entry point // Import the RTK Query methods from the React-specific entry point
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react' import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
import { createSelector} from '@reduxjs/toolkit' import { createSelector } from '@reduxjs/toolkit'
// Define our single API slice object // Define our single API slice object
export const apiSlice = createApi({ export const apiSlice = createApi({
// The cache reducer expects to be added at `state.api` (already default - this is optional) // The cache reducer expects to be added at `state.api` (already default - this is optional)
reducerPath: 'api', reducerPath: 'api',
// All of our requests will have URLs starting with '/fakeApi' // All of our requests will have URLs starting with '/fakeApi'
baseQuery: fetchBaseQuery({ baseUrl: process.env.REACT_APP_ADMIN_SERVER}), baseQuery: fetchBaseQuery({ baseUrl: process.env.REACT_APP_ADMIN_SERVER }),
// The "endpoints" represent operations and requests for this server // The "endpoints" represent operations and requests for this server
endpoints: builder => ({ endpoints: builder => ({
// The `getPosts` endpoint is a "query" operation that returns data // The `getPosts` endpoint is a "query" operation that returns data
getTalkgroups: builder.query({ getTalkgroups: builder.query({
// The URL for the request is '/fakeApi/posts' // The URL for the request is '/fakeApi/posts'
query: (shortName) => ({ url: `/talkgroups/${shortName}`, credentials: "include" }) query: (shortName) => ({ url: `/talkgroups/${shortName}`, credentials: "include" })
}), }),
getGroups: builder.query({ getGroups: builder.query({
// The URL for the request is '/fakeApi/posts' // The URL for the request is '/fakeApi/posts'
query: (shortName) => ({ url: `/groups/${shortName}`, credentials: "include" }) query: (shortName) => ({ url: `/groups/${shortName}`, credentials: "include" }),
}), providesTags: (result, error, arg) =>
getErrors: builder.query({ result
// The URL for the request is '/fakeApi/posts' ? [...result.map(({ _id }) => ({ type: 'Group', _id })), 'Group']
query: (shortName) => ({ url: `${process.env.REACT_APP_BACKEND_SERVER}/${shortName}/errors`}) : ['Group'],
}), }),
updateGroup: builder.mutation({
query: (group) => ({
url: `/groups/${group.shortName}/${group._id}`,
method: 'POST',
credentials: "include",
body: group,
}),
async onQueryStarted(group, { dispatch, queryFulfilled }) {
try {
const { data: updatedGroup } = await queryFulfilled
const patchResult = dispatch(
apiSlice.util.updateQueryData('getGroups', updatedGroup.shortName, (groups) => {
const groupIndex = groups.findIndex((obj => obj.groupId == updatedGroup.groupId));
groups[groupIndex] = updatedGroup;
})
)
} catch {}
},
}),
createGroup: builder.mutation({
query: (group) => ({
url: `/groups/${group.shortName}`,
method: 'POST',
credentials: "include",
body: group,
}),
async onQueryStarted(group, { dispatch, queryFulfilled }) {
try {
const { data: newGroup } = await queryFulfilled;
const patchResult = dispatch(
apiSlice.util.updateQueryData('getGroups', newGroup.shortName, (groups) => {
groups.push(newGroup);
})
)
} catch {}
},
}),
getSystems: builder.query({
// The URL for the request is '/fakeApi/posts'
query: () => ({ url: `/systems`, credentials: "include" })
})
getErrors: builder.query({
// The URL for the request is '/fakeApi/posts'
query: (shortName) => ({ url: `${process.env.REACT_APP_BACKEND_SERVER}/${shortName}/errors` })
}),
updateGroup: builder.mutation({
query: (group) => ({
url: `/groups/${group.shortName}/${group._id}`,
method: 'POST',
credentials: "include",
body: group,
}),
async onQueryStarted(group, { dispatch, queryFulfilled }) {
try {
const { data: updatedGroup } = await queryFulfilled
const patchResult = dispatch(
apiSlice.util.updateQueryData('getGroups', updatedGroup.shortName, (groups) => {
const groupIndex = groups.findIndex((obj => obj.groupId == updatedGroup.groupId));
groups[groupIndex] = updatedGroup;
})
)
} catch { }
},
}),
createGroup: builder.mutation({
query: (group) => ({
url: `/groups/${group.shortName}`,
method: 'POST',
credentials: "include",
body: group,
}),
async onQueryStarted(group, { dispatch, queryFulfilled }) {
try {
const { data: newGroup } = await queryFulfilled;
const patchResult = dispatch(
apiSlice.util.updateQueryData('getGroups', newGroup.shortName, (groups) => {
groups.push(newGroup);
})
)
} catch { }
},
}),
deleteGroup: builder.mutation({
query: (group) => ({
url: `/groups/${group.shortName}/${group._id}`,
method: 'DELETE',
credentials: "include"
}),
invalidatesTags: (result, error, group) => [{ type: 'Group', id: group._id }],
}),
saveGroupOrder: builder.mutation({
query: ({shortName, order}) => ({
url: `/groups/${shortName}/reorder`,
method: 'POST',
credentials: "include",
body: order,
}),
//invalidatesTags: (result, error, group) => ['Group'],
}),
getSystems: builder.query({
// The URL for the request is '/fakeApi/posts'
query: () => ({ url: `/systems`, credentials: "include" })
}) })
})
}) })
// Export the auto-generated hook for the `getPosts` query endpoint // Export the auto-generated hook for the `getPosts` query endpoint
export const { useGetGroupsQuery, useGetSystemsQuery, useGetTalkgroupsQuery, useGetErrorsQuery} = apiSlice export const { useGetGroupsQuery, useGetSystemsQuery, useGetTalkgroupsQuery, useGetErrorsQuery, useDeleteGroupMutation, useCreateGroupMutation, useSaveGroupOrderMutation, useUpdateGroupMutation } = apiSlice