mirror of
https://github.com/openmhz/trunk-server.git
synced 2026-11-14 17:58:02 -05:00
add some basic drag and drop
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import React from "react";
|
import React, { useState } from "react";
|
||||||
import {
|
import {
|
||||||
Header,
|
Header,
|
||||||
Divider,
|
Divider,
|
||||||
@@ -6,81 +6,108 @@ import {
|
|||||||
Segment,
|
Segment,
|
||||||
Statistic,
|
Statistic,
|
||||||
Icon,
|
Icon,
|
||||||
Menu
|
Menu,
|
||||||
|
Tab
|
||||||
} from "semantic-ui-react";
|
} from "semantic-ui-react";
|
||||||
|
import PlaylistBuilder from "./PlaylistBuilder"
|
||||||
// ----------------------------------------------------
|
// ----------------------------------------------------
|
||||||
function CallInfo(props) {
|
function CallInfo(props) {
|
||||||
let srcList = "";
|
|
||||||
let callLength = "-";
|
|
||||||
let callFreq = "-";
|
|
||||||
let callDate = "-";
|
|
||||||
let callTime = "-";
|
|
||||||
let talkgroupNum = "-";
|
|
||||||
let callDownload = "";
|
|
||||||
let callTweet = "";
|
|
||||||
if (props.call) {
|
|
||||||
const currentCall = props.call;
|
|
||||||
var time = new Date(currentCall.time);
|
|
||||||
callTime = time.toLocaleTimeString();
|
|
||||||
callDate = time.toLocaleDateString();
|
|
||||||
if (currentCall.freq) {
|
|
||||||
var freq = currentCall.freq / 1000000;
|
|
||||||
callFreq = Math.round(freq * 1000) / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
srcList = currentCall.srcList.map((source, index) => <List.Item key={index}>{source.src}[{source.pos}]</List.Item>);
|
|
||||||
callLength = currentCall.len;
|
|
||||||
talkgroupNum = currentCall.talkgroupNum;
|
let srcList = "";
|
||||||
callDownload = currentCall.url;
|
let callLength = "-";
|
||||||
callTweet = "https://twitter.com/intent/tweet?url="+encodeURIComponent(document.location.origin+props.link)+"&via="+encodeURIComponent("OpenMHz");
|
let callFreq = "-";
|
||||||
|
let callDate = "-";
|
||||||
|
let callTime = "-";
|
||||||
|
let talkgroupNum = "-";
|
||||||
|
let callDownload = "";
|
||||||
|
let callTweet = "";
|
||||||
|
if (props.call) {
|
||||||
|
const currentCall = props.call;
|
||||||
|
var time = new Date(currentCall.time);
|
||||||
|
callTime = time.toLocaleTimeString();
|
||||||
|
callDate = time.toLocaleDateString();
|
||||||
|
if (currentCall.freq) {
|
||||||
|
var freq = currentCall.freq / 1000000;
|
||||||
|
callFreq = Math.round(freq * 1000) / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
srcList = currentCall.srcList.map((source, index) => <List.Item key={index}>{source.src}[{source.pos}]</List.Item>);
|
||||||
<div>
|
callLength = currentCall.len;
|
||||||
<Segment padded attached>
|
talkgroupNum = currentCall.talkgroupNum;
|
||||||
<Header as='h1'>{props.header}</Header>
|
callDownload = currentCall.url;
|
||||||
<List bulleted horizontal link>
|
callTweet = "https://twitter.com/intent/tweet?url=" + encodeURIComponent(document.location.origin + props.link) + "&via=" + encodeURIComponent("OpenMHz");
|
||||||
{srcList}
|
|
||||||
</List>
|
|
||||||
<Divider/>
|
|
||||||
<Statistic size='small'>
|
|
||||||
<Statistic.Label>Seconds</Statistic.Label>
|
|
||||||
<Statistic.Value>{callLength}</Statistic.Value>
|
|
||||||
</Statistic>
|
|
||||||
<Statistic size='small'>
|
|
||||||
<Statistic.Label>Talkgroup</Statistic.Label>
|
|
||||||
<Statistic.Value>{talkgroupNum}</Statistic.Value>
|
|
||||||
</Statistic>
|
|
||||||
|
|
||||||
<List divided verticalAlign='middle'>
|
|
||||||
<List.Item>
|
|
||||||
<Icon name="wait"/>
|
|
||||||
<List.Content>
|
|
||||||
{callTime}
|
|
||||||
</List.Content>
|
|
||||||
</List.Item>
|
|
||||||
<List.Item>
|
|
||||||
<Icon name="calendar outline"/>
|
|
||||||
<List.Content>
|
|
||||||
{callDate}
|
|
||||||
</List.Content>
|
|
||||||
</List.Item>
|
|
||||||
<List.Item>
|
|
||||||
<Icon name="cubes"/>
|
|
||||||
<List.Content>
|
|
||||||
{callFreq} MHz
|
|
||||||
</List.Content>
|
|
||||||
</List.Item>
|
|
||||||
</List>
|
|
||||||
</Segment>
|
|
||||||
<Menu attached='bottom'>
|
|
||||||
<a href={callTweet}><Menu.Item name="tweet" ><Icon name='twitter' />Tweet</Menu.Item></a>
|
|
||||||
<a href={callDownload}><Menu.Item name="download"><Icon name="download" />Download</Menu.Item></a>
|
|
||||||
<a href={props.link}><Menu.Item name="link"><Icon name="at" />Link</Menu.Item></a>
|
|
||||||
</Menu>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
const [activeTab, setActiveTab] = useState(0);
|
||||||
|
const handleTabChange = (e, data) => setActiveTab(data.activeIndex);
|
||||||
|
|
||||||
export default CallInfo;
|
|
||||||
|
|
||||||
|
const panes = [
|
||||||
|
{
|
||||||
|
menuItem: 'Call Info', render: () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Tab.Pane attached='bottom'>
|
||||||
|
<List bulleted horizontal link>
|
||||||
|
{srcList}
|
||||||
|
</List>
|
||||||
|
<Divider />
|
||||||
|
<Statistic size='small'>
|
||||||
|
<Statistic.Label>Seconds</Statistic.Label>
|
||||||
|
<Statistic.Value>{callLength}</Statistic.Value>
|
||||||
|
</Statistic>
|
||||||
|
<Statistic size='small'>
|
||||||
|
<Statistic.Label>Talkgroup</Statistic.Label>
|
||||||
|
<Statistic.Value>{talkgroupNum}</Statistic.Value>
|
||||||
|
</Statistic>
|
||||||
|
|
||||||
|
<List divided verticalAlign='middle'>
|
||||||
|
<List.Item>
|
||||||
|
<Icon name="wait" />
|
||||||
|
<List.Content>
|
||||||
|
{callTime}
|
||||||
|
</List.Content>
|
||||||
|
</List.Item>
|
||||||
|
<List.Item>
|
||||||
|
<Icon name="calendar outline" />
|
||||||
|
<List.Content>
|
||||||
|
{callDate}
|
||||||
|
</List.Content>
|
||||||
|
</List.Item>
|
||||||
|
<List.Item>
|
||||||
|
<Icon name="cubes" />
|
||||||
|
<List.Content>
|
||||||
|
{callFreq} MHz
|
||||||
|
</List.Content>
|
||||||
|
</List.Item>
|
||||||
|
</List>
|
||||||
|
|
||||||
|
</Tab.Pane>
|
||||||
|
<Menu>
|
||||||
|
<a href={callTweet}><Menu.Item name="tweet" ><Icon name='twitter' />Tweet</Menu.Item></a>
|
||||||
|
<a href={callDownload}><Menu.Item name="download"><Icon name="download" />Download</Menu.Item></a>
|
||||||
|
<a href={props.link}><Menu.Item name="link"><Icon name="at" />Link</Menu.Item></a>
|
||||||
|
</Menu>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
menuItem: 'Playlist', render: () => {
|
||||||
|
return (
|
||||||
|
<PlaylistBuilder />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Tab menu={{ attached: 'top' }} panes={panes} defaultActiveIndex={activeTab} onTabChange={handleTabChange} />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CallInfo;
|
||||||
|
|||||||
@@ -34,6 +34,23 @@ const CallItem = (props) => {
|
|||||||
var rowSelected = {};
|
var rowSelected = {};
|
||||||
let starButton;
|
let starButton;
|
||||||
var starClickable = {};
|
var starClickable = {};
|
||||||
|
|
||||||
|
const onDragStart = (event) => {
|
||||||
|
// It receives a DragEvent
|
||||||
|
// which inherits properties from
|
||||||
|
// MouseEvent and Event
|
||||||
|
// so we can access the element
|
||||||
|
// through event.currentTarget
|
||||||
|
|
||||||
|
// Later, we'll save
|
||||||
|
// in a hook variable
|
||||||
|
// the item being dragged
|
||||||
|
const callId = event.currentTarget.dataset.callid;
|
||||||
|
event.dataTransfer.setData("call-id", callId);
|
||||||
|
console.log("Dragging: " + callId);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (!starClicked) {
|
if (!starClicked) {
|
||||||
starClickable = { link: true };
|
starClickable = { link: true };
|
||||||
}
|
}
|
||||||
@@ -68,7 +85,7 @@ const CallItem = (props) => {
|
|||||||
talkgroup = props.talkgroups[call.talkgroupNum].description;
|
talkgroup = props.talkgroups[call.talkgroupNum].description;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Table.Row onClick={(e) => props.onClick({ call: call }, e)} {...rowSelected}>
|
<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> {call.len} </Table.Cell>
|
||||||
<Table.Cell> {talkgroup} </Table.Cell>
|
<Table.Cell> {talkgroup} </Table.Cell>
|
||||||
<Table.Cell> {time.toLocaleTimeString()} </Table.Cell>
|
<Table.Cell> {time.toLocaleTimeString()} </Table.Cell>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { Component, useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useGetGroupsQuery } from '../features/api/apiSlice'
|
import { useGetGroupsQuery } from '../features/api/apiSlice'
|
||||||
import { setGroupFilter } from "../features/callPlayer/callPlayerSlice";
|
import { setGroupFilter } from "../features/callPlayer/callPlayerSlice";
|
||||||
import { useSelector, useDispatch } from 'react-redux'
|
import { useSelector, useDispatch } from 'react-redux'
|
||||||
@@ -12,7 +12,6 @@ import {
|
|||||||
import "./FilterModal.css";
|
import "./FilterModal.css";
|
||||||
|
|
||||||
function GroupModal (props) {
|
function GroupModal (props) {
|
||||||
const shortName = useSelector((state) => state.callPlayer.shortName);
|
|
||||||
const { data, isError, isLoading, isSuccess,error } = useGetGroupsQuery(props.shortName);
|
const { data, isError, isLoading, isSuccess,error } = useGetGroupsQuery(props.shortName);
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [selectedGroup, setSelectedGroup] = useState(false);
|
const [selectedGroup, setSelectedGroup] = useState(false);
|
||||||
|
|||||||
49
frontend/src/Call/PlaylistBuilder.js
Normal file
49
frontend/src/Call/PlaylistBuilder.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import { useSelector, useDispatch } from 'react-redux'
|
||||||
|
|
||||||
|
import {
|
||||||
|
Header,
|
||||||
|
Divider,
|
||||||
|
List,
|
||||||
|
Segment,
|
||||||
|
Statistic,
|
||||||
|
Icon,
|
||||||
|
Menu,
|
||||||
|
Tab
|
||||||
|
} from "semantic-ui-react";
|
||||||
|
|
||||||
|
function PlaylistBuilder(props) {
|
||||||
|
|
||||||
|
const { loading: callsLoading, data: callsData } = useSelector((state) => state.calls);
|
||||||
|
|
||||||
|
const onDragOver = (event) => {
|
||||||
|
// It also receives a DragEvent.
|
||||||
|
// Later, we'll read the position
|
||||||
|
// of the item from event.currentTarget
|
||||||
|
// and store the updated list state
|
||||||
|
|
||||||
|
// We need to prevent the default behavior
|
||||||
|
// of this event, in order for the onDrop
|
||||||
|
// event to fire.
|
||||||
|
// It may sound weird, but the default is
|
||||||
|
// to cancel out the drop.
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
const onDrop = (event) => {
|
||||||
|
// Here, we will:
|
||||||
|
// - update the rendered list
|
||||||
|
// - and reset the DnD state
|
||||||
|
var callId = event.dataTransfer.getData("call-id");
|
||||||
|
console.log("Dropping: " + callId);
|
||||||
|
console.log("Found: " + callsData.entities[callId].freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tab.Pane attached='bottom'>
|
||||||
|
<div onDragOver={onDragOver} onDrop={onDrop}>Placeholder</div>
|
||||||
|
</Tab.Pane>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PlaylistBuilder;
|
||||||
Reference in New Issue
Block a user