aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton.tananaev@gmail.com>2022-08-02 07:52:11 -0700
committerGitHub <noreply@github.com>2022-08-02 07:52:11 -0700
commit114c78dff8fbfdc19444c88fea45188012065a3a (patch)
tree381cf86554596fc7deb004118b8fca7109c9758f
parent0d9573c2145a6e2df3d43ef4e192529654bc65de (diff)
parenta769c2d1206e86cf446ffdf8c7b68ef834624d0a (diff)
downloadtrackermap-web-114c78dff8fbfdc19444c88fea45188012065a3a.tar.gz
trackermap-web-114c78dff8fbfdc19444c88fea45188012065a3a.tar.bz2
trackermap-web-114c78dff8fbfdc19444c88fea45188012065a3a.zip
Merge pull request #1001 from lzkill/floating-status-card
Floating status card
-rw-r--r--modern/package-lock.json23
-rw-r--r--modern/package.json1
-rw-r--r--modern/src/main/StatusCard.js161
3 files changed, 111 insertions, 74 deletions
diff --git a/modern/package-lock.json b/modern/package-lock.json
index 248eca60..7265f0e3 100644
--- a/modern/package-lock.json
+++ b/modern/package-lock.json
@@ -25,6 +25,7 @@
"moment": "^2.29.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-draggable": "^4.4.5",
"react-mui-dropzone": "^4.0.6",
"react-redux": "^8.0.2",
"react-router-dom": "^6.3.0",
@@ -16417,6 +16418,19 @@
"react": "^18.2.0"
}
},
+ "node_modules/react-draggable": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.5.tgz",
+ "integrity": "sha512-OMHzJdyJbYTZo4uQE393fHcqqPYsEtkjfMgvCHr6rejT+Ezn4OZbNyGH50vv+SunC1RMvwOTSWkEODQLzw1M9g==",
+ "dependencies": {
+ "clsx": "^1.1.1",
+ "prop-types": "^15.8.1"
+ },
+ "peerDependencies": {
+ "react": ">= 16.3.0",
+ "react-dom": ">= 16.3.0"
+ }
+ },
"node_modules/react-dropzone": {
"version": "10.2.2",
"resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-10.2.2.tgz",
@@ -31670,6 +31684,15 @@
"scheduler": "^0.23.0"
}
},
+ "react-draggable": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.4.5.tgz",
+ "integrity": "sha512-OMHzJdyJbYTZo4uQE393fHcqqPYsEtkjfMgvCHr6rejT+Ezn4OZbNyGH50vv+SunC1RMvwOTSWkEODQLzw1M9g==",
+ "requires": {
+ "clsx": "^1.1.1",
+ "prop-types": "^15.8.1"
+ }
+ },
"react-dropzone": {
"version": "10.2.2",
"resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-10.2.2.tgz",
diff --git a/modern/package.json b/modern/package.json
index 5e50d70d..e34cb7e0 100644
--- a/modern/package.json
+++ b/modern/package.json
@@ -20,6 +20,7 @@
"moment": "^2.29.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
+ "react-draggable": "^4.4.5",
"react-mui-dropzone": "^4.0.6",
"react-redux": "^8.0.2",
"react-router-dom": "^6.3.0",
diff --git a/modern/src/main/StatusCard.js b/modern/src/main/StatusCard.js
index 373b02ab..5ca45066 100644
--- a/modern/src/main/StatusCard.js
+++ b/modern/src/main/StatusCard.js
@@ -1,6 +1,7 @@
import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useNavigate } from 'react-router-dom';
+import Draggable from 'react-draggable';
import {
Card,
CardContent,
@@ -155,82 +156,94 @@ const StatusCard = ({ deviceId, onClose }) => {
return (
<>
{device && (
- <Card elevation={3} className={classes.card}>
- {deviceImage ? (
- <CardMedia
- className={classes.media}
- image={`/api/media/${device.uniqueId}/${deviceImage}`}
- >
- <IconButton size="small" onClick={onClose}>
- <CloseIcon fontSize="small" className={classes.mediaButton} />
+ <Draggable
+ handle={`.${classes.media}, .${classes.header}`}
+ >
+ <Card elevation={3} className={classes.card}>
+ {deviceImage ? (
+ <CardMedia
+ className={classes.media}
+ image={`/api/media/${device.uniqueId}/${deviceImage}`}
+ >
+ <IconButton
+ size="small"
+ onClick={onClose}
+ onTouchStart={onClose}
+ >
+ <CloseIcon fontSize="small" className={classes.mediaButton} />
+ </IconButton>
+ </CardMedia>
+ ) : (
+ <div className={classes.header}>
+ <Typography variant="body2" color="textSecondary">
+ {device.name}
+ </Typography>
+ <IconButton
+ size="small"
+ onClick={onClose}
+ onTouchStart={onClose}
+ >
+ <CloseIcon fontSize="small" />
+ </IconButton>
+ </div>
+ )}
+ {position && (
+ <CardContent className={classes.content}>
+ <Table size="small" classes={{ root: classes.table }}>
+ <TableBody>
+ {positionItems.filter((key) => position.hasOwnProperty(key) || position.attributes.hasOwnProperty(key)).map((key) => (
+ <StatusRow
+ key={key}
+ name={positionAttributes[key].name}
+ content={(
+ <PositionValue
+ position={position}
+ property={position.hasOwnProperty(key) ? key : null}
+ attribute={position.hasOwnProperty(key) ? null : key}
+ />
+ )}
+ />
+ ))}
+ </TableBody>
+ </Table>
+ </CardContent>
+ )}
+ <CardActions classes={{ root: classes.actions }} disableSpacing>
+ <IconButton
+ color="secondary"
+ onClick={(e) => setAnchorEl(e.currentTarget)}
+ disabled={!position}
+ >
+ <PendingIcon />
</IconButton>
- </CardMedia>
- ) : (
- <div className={classes.header}>
- <Typography variant="body2" color="textSecondary">
- {device.name}
- </Typography>
- <IconButton size="small" onClick={onClose}>
- <CloseIcon fontSize="small" />
+ <IconButton
+ onClick={() => navigate('/replay')}
+ disabled={!position}
+ >
+ <ReplayIcon />
</IconButton>
- </div>
- )}
- {position && (
- <CardContent className={classes.content}>
- <Table size="small" classes={{ root: classes.table }}>
- <TableBody>
- {positionItems.filter((key) => position.hasOwnProperty(key) || position.attributes.hasOwnProperty(key)).map((key) => (
- <StatusRow
- key={key}
- name={positionAttributes[key].name}
- content={(
- <PositionValue
- position={position}
- property={position.hasOwnProperty(key) ? key : null}
- attribute={position.hasOwnProperty(key) ? null : key}
- />
- )}
- />
- ))}
- </TableBody>
- </Table>
- </CardContent>
- )}
- <CardActions classes={{ root: classes.actions }} disableSpacing>
- <IconButton
- color="secondary"
- onClick={(e) => setAnchorEl(e.currentTarget)}
- disabled={!position}
- >
- <PendingIcon />
- </IconButton>
- <IconButton
- onClick={() => navigate('/replay')}
- disabled={!position}
- >
- <ReplayIcon />
- </IconButton>
- <IconButton
- onClick={() => navigate(`/settings/command-send/${deviceId}`)}
- disabled={readonly}
- >
- <PublishIcon />
- </IconButton>
- <IconButton
- onClick={() => navigate(`/settings/device/${deviceId}`)}
- disabled={deviceReadonly}
- >
- <EditIcon />
- </IconButton>
- <IconButton
- onClick={() => setRemoving(true)}
- disabled={deviceReadonly}
- className={classes.negative}
- >
- <DeleteIcon />
- </IconButton>
- </CardActions>
- </Card>
+ <IconButton
+ onClick={() => navigate(`/settings/command-send/${deviceId}`)}
+ disabled={readonly}
+ >
+ <PublishIcon />
+ </IconButton>
+ <IconButton
+ onClick={() => navigate(`/settings/device/${deviceId}`)}
+ disabled={deviceReadonly}
+ >
+ <EditIcon />
+ </IconButton>
+ <IconButton
+ onClick={() => setRemoving(true)}
+ disabled={deviceReadonly}
+ className={classes.negative}
+ >
+ <DeleteIcon />
+ </IconButton>
+ </CardActions>
+ </Card>
+ </Draggable>
)}
{position && (
<Menu anchorEl={anchorEl} open={Boolean(anchorEl)} onClose={() => setAnchorEl(null)}>