From 3c1fb0ead9ba4db376cb2751e178fe08ca4b0b75 Mon Sep 17 00:00:00 2001 From: HF Date: Tue, 2 Aug 2022 14:54:45 +0200 Subject: [PATCH] add Watchtools basics --- src/components/ModWatchtools.jsx | 260 +++++++++++++++++++++++++++++++ src/components/Modtools.jsx | 6 +- 2 files changed, 264 insertions(+), 2 deletions(-) create mode 100644 src/components/ModWatchtools.jsx diff --git a/src/components/ModWatchtools.jsx b/src/components/ModWatchtools.jsx new file mode 100644 index 0000000..f6a3f3b --- /dev/null +++ b/src/components/ModWatchtools.jsx @@ -0,0 +1,260 @@ +/* + * ModWatchtools + * Tools to check who placed what where + */ + +import React, { useState, useEffect } from 'react'; +import { useSelector, shallowEqual } from 'react-redux'; +import { t } from 'ttag'; + +const keepState = { + tlcoords: '', + brcoords: '', + interval: '15m', + iid: '', +}; + +function parseInterval(interval) { + if (!interval) { + return null; + } + const lastChar = interval.slice(-1).toLowerCase(); + const num = parseInt(interval.slice(0, -1), 10); + if (Number.isNaN(num) || num <= 0 || num > 600 + || !['s', 'm', 'h'].includes(lastChar)) { + return null; + } + let factor = 1000; + if (lastChar === 'm') { + factor *= 60; + } else if (lastChar === 'h') { + factor *= 3600; + } + return Date.now() - (num * factor); +} + +async function submitWatchAction( + action, + canvas, + tlcoords, + brcoords, + interval, + iid, + callback, +) { + const time = parseInterval(interval); + if (!time) { + callback({ info: t`Interval is invalid` }); + return; + } + const data = new FormData(); + data.append('watchaction', action); + data.append('ulcoor', tlcoords); + data.append('brcoor', brcoords); + data.append('time', time); + data.append('iid', iid); + try { + const resp = await fetch('./api/modtools', { + credentials: 'include', + method: 'POST', + body: data, + }); + const ret = await resp.json(); + callback(await ret); + } catch (err) { + callback({ + info: `Error: ${err.message}`, + }); + } +} + +function ModWatchtools() { + const [selectedCanvas, selectCanvas] = useState(0); + const [tlcoords, selectTLCoords] = useState(keepState.tlcoords); + const [brcoords, selectBRCoords] = useState(keepState.brcoords); + const [interval, selectInterval] = useState(keepState.interval); + const [iid, selectIid] = useState(keepState.iid); + const [resp, setResp] = useState(null); + const [submitting, setSubmitting] = useState(false); + + const [ + canvasId, + canvases, + ] = useSelector((state) => [ + state.canvas.canvasId, + state.canvas.canvases, + ], shallowEqual); + + useEffect(() => { + selectCanvas(canvasId); + }, [canvasId]); + + return ( +
+ {resp && ( +
+ {resp.split('\n').map((line) => ( +

+ {line} +

+ ))} + setResp(null)} + > + {t`Close`} + +
+ )} +

{t`Check who placed in an area`}

+

{t`Canvas`}:  + + {` ${t`Interval`}: `} + { + const newInterval = evt.target.value.trim(); + selectInterval(newInterval); + keepState.interval = newInterval; + }} + /> + {` ${t`IID (optional)`}: `} + { + const newIid = evt.target.value.trim(); + selectIid(newIid); + keepState.iid = newIid; + }} + /> +

+

+ {t`Top-left corner`} (X_Y):  + { + const co = evt.target.value.trim(); + selectTLCoords(co); + keepState.tlcoords = co; + }} + /> +

+

+ {t`Bottom-right corner`} (X_Y):  + { + const co = evt.target.value.trim(); + selectBRCoords(co); + keepState.brcoords = co; + }} + /> +

+ + +
+ ); +} + +export default React.memo(ModWatchtools); diff --git a/src/components/Modtools.jsx b/src/components/Modtools.jsx index 98a0827..e381ce0 100644 --- a/src/components/Modtools.jsx +++ b/src/components/Modtools.jsx @@ -5,13 +5,15 @@ import React, { useState } from 'react'; import { useSelector } from 'react-redux'; -import ModCanvastools from './ModCanvastools'; +import Canvastools from './ModCanvastools'; import Admintools from './Admintools'; +import Watchtools from './ModWatchtools'; const CONTENT = { - Canvas: ModCanvastools, + Canvas: Canvastools, Admin: Admintools, + Watch: Watchtools, }; function Modtools() {