From 98467ef7f6f55ccbd8b80f38f852690222eb7156 Mon Sep 17 00:00:00 2001 From: dhruvkhanna38 <34186136+dhruvkhanna38@users.noreply.github.com> Date: Sat, 27 May 2023 13:14:56 -0700 Subject: [PATCH 1/5] Created a new path /DemoCopyStream with button to copy data collected from microbit as .csv --- package.json | 1 + src/index.jsx | 10 ++ src/pages/DemoCopyStream.tsx | 315 +++++++++++++++++++++++++++++++++++ src/pages/Index.tsx | 1 + yarn.lock | 37 +++- 5 files changed, 360 insertions(+), 4 deletions(-) create mode 100644 src/pages/DemoCopyStream.tsx diff --git a/package.json b/package.json index 38cc2ed..d51b426 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "@types/node": "^16.11.6", "d3": "^7.1.1", "jacdac-ts": "^1.24.20", + "react-copy-to-clipboard": "^5.1.0", "react-jacdac": "^1.1.3", "rxjs": "^7.5.2", "rxjs-spy": "^8.0.2", diff --git a/src/index.jsx b/src/index.jsx index 53e8c1f..6dab3a3 100644 --- a/src/index.jsx +++ b/src/index.jsx @@ -4,6 +4,7 @@ import { Demo } from './pages/Demo' const Jacdac = lazy(() => import('./pages/Jacdac')) const Dashboard = lazy(() => import('./pages/Dashboard')) const MicrobitController = lazy(() => import('./pages/MicrobitController')) +const DemoCopyStream = lazy(() => import('./pages/DemoCopyStream')) import { HashRouter, Routes, Route } from 'react-router-dom' import Index from './pages/Index' @@ -17,6 +18,15 @@ ReactDOM.render( } /> } /> + + + + } + /> + , for the sink to subscribe. + * Source: https://stackoverflow.com/questions/57999777/filter-undefined-from-rxjs-observable + * @returns observable + */ + +function filterNullish(): UnaryFunction, Observable> { + return pipe(filter((x) => x != null) as OperatorFunction) +} + +/** + * Helper function to copy data to the clipboard and remove data from the clipboard. + * @param {Object} props - Component props + * @param {Array} props.xData - X data array + * @param {Array} props.yData - Y data array + * @param {Array} props.zData - Z data array + * @param {Object} props.textareaRef - Reference to the textarea element + * @param {Function} props.setCopied - Setter function for the copied state + * @param {boolean} props.copied - Copied state indicating whether the data has been copied + * @param {Function} props.setXStreamData - Setter function for the X stream data + * @param {Function} props.setYStreamData - Setter function for the Y stream data + * @param {Function} props.setZStreamData - Setter function for the Z stream data + * @returns {JSX.Element} - Copy to clipboard button component + */ + +function CopyToClipboardButton(props) { + const { xData, yData, zData, textareaRef, setCopied, copied, setXStreamData, setYStreamData, setZStreamData } = + props + const dataExists = xData.length > 0 || yData.length > 0 || zData.length > 0 + const dataRows: string[] = [] + const [totalCount, setTotalCount] = useState(0) + const copyToClipboard = async () => { + if (!dataExists || !textareaRef.current) return + const header = 'x,y,z' + + if (dataExists) { + const maxLength = Math.max(xData.length, yData.length, zData.length) + for (let i = 0; i < maxLength; i++) { + const xValue = xData[i]?.value ?? '' + const yValue = yData[i]?.value ?? '' + const zValue = zData[i]?.value ?? '' + dataRows.push(`${xValue},${yValue},${zValue}`) + } + } + + const csv = [header, ...dataRows].join('\n') + + textareaRef.current.value = csv + textareaRef.current.select() + try { + await navigator.clipboard.writeText(csv) + setCopied(true) + setTotalCount(dataRows.length) + } catch (error) { + console.error('Failed to copy to clipboard:', error) + } + } + + const removeFromClipboard = () => { + if (textareaRef.current) { + textareaRef.current.value = '' + navigator.clipboard.writeText('') // Clear the clipboard + setCopied(false) + setTotalCount(0) + } + // Clear the input stream data + setXStreamData([]) + setYStreamData([]) + setZStreamData([]) + } + + useEffect(() => { + if (copied) { + const timeout = setTimeout(() => setCopied(false), 2000) + return () => clearTimeout(timeout) + } + }, [copied]) + + return ( + <> + + +

Total values collected: {totalCount}

{/* Display the total count */} +