aboutsummaryrefslogtreecommitdiff
path: root/modern/src/common/components
diff options
context:
space:
mode:
authorAnton Tananaev <anton@traccar.org>2023-11-25 14:19:35 -0800
committerAnton Tananaev <anton@traccar.org>2023-11-25 14:19:41 -0800
commit4a7ab9a9b45a43b285e5d649d8f25e821f376ac3 (patch)
tree98fbb592e56f404de9adb6b070c55531da0f3617 /modern/src/common/components
parenta1dce943fc3f7075b5d2fd887cb9b2f30402f73e (diff)
downloadtrackermap-web-4a7ab9a9b45a43b285e5d649d8f25e821f376ac3.tar.gz
trackermap-web-4a7ab9a9b45a43b285e5d649d8f25e821f376ac3.tar.bz2
trackermap-web-4a7ab9a9b45a43b285e5d649d8f25e821f376ac3.zip
Add device sharing (fix #1118)
Diffstat (limited to 'modern/src/common/components')
-rw-r--r--modern/src/common/components/StatusCard.jsx20
1 files changed, 20 insertions, 0 deletions
diff --git a/modern/src/common/components/StatusCard.jsx b/modern/src/common/components/StatusCard.jsx
index 04e1d172..2e936420 100644
--- a/modern/src/common/components/StatusCard.jsx
+++ b/modern/src/common/components/StatusCard.jsx
@@ -1,6 +1,7 @@
import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useNavigate } from 'react-router-dom';
+import dayjs from 'dayjs';
import Draggable from 'react-draggable';
import {
Card,
@@ -15,6 +16,7 @@ import {
Menu,
MenuItem,
CardMedia,
+ Snackbar,
} from '@mui/material';
import makeStyles from '@mui/styles/makeStyles';
import CloseIcon from '@mui/icons-material/Close';
@@ -130,6 +132,7 @@ const StatusCard = ({ deviceId, position, onClose, disableActions, desktopPaddin
const [anchorEl, setAnchorEl] = useState(null);
const [removing, setRemoving] = useState(false);
+ const [shared, setShared] = useState(false);
const handleRemove = useCatch(async (removed) => {
if (removed) {
@@ -169,6 +172,21 @@ const StatusCard = ({ deviceId, position, onClose, disableActions, desktopPaddin
}
}, [navigate, position]);
+ const handleShare = useCatchCallback(async () => {
+ const expiration = dayjs().add(1, 'week').toISOString();
+ const response = await fetch('/api/devices/share', {
+ method: 'POST',
+ body: new URLSearchParams(`deviceId=${deviceId}&expiration=${expiration}`),
+ });
+ if (response.ok) {
+ const token = await response.text();
+ navigator.clipboard.writeText(`${window.location.origin}?token=${token}`);
+ setShared(true);
+ } else {
+ throw Error(await response.text());
+ }
+ }, [deviceId, setShared]);
+
return (
<>
<div className={classes.root}>
@@ -270,6 +288,7 @@ const StatusCard = ({ deviceId, position, onClose, disableActions, desktopPaddin
<MenuItem component="a" target="_blank" href={`https://www.google.com/maps/search/?api=1&query=${position.latitude}%2C${position.longitude}`}>{t('linkGoogleMaps')}</MenuItem>
<MenuItem component="a" target="_blank" href={`http://maps.apple.com/?ll=${position.latitude},${position.longitude}`}>{t('linkAppleMaps')}</MenuItem>
<MenuItem component="a" target="_blank" href={`https://www.google.com/maps/@?api=1&map_action=pano&viewpoint=${position.latitude}%2C${position.longitude}&heading=${position.course}`}>{t('linkStreetView')}</MenuItem>
+ <MenuItem onClick={handleShare}>{t('deviceShare')}</MenuItem>
</Menu>
)}
<RemoveDialog
@@ -278,6 +297,7 @@ const StatusCard = ({ deviceId, position, onClose, disableActions, desktopPaddin
itemId={deviceId}
onResult={(removed) => handleRemove(removed)}
/>
+ <Snackbar open={shared} onClose={() => setShared(false)} message={t('sharedLinkCopied')} />
</>
);
};