feat: Add file path copying functionality to CSV File Browser and update PlotJuggler launch command

This commit is contained in:
Miguel 2025-08-15 20:29:17 +02:00
parent 3a830fe100
commit 02b622cb20
3 changed files with 109 additions and 5 deletions

View File

@ -59,7 +59,8 @@ import {
FaCalendar,
FaDatabase,
FaSync,
FaCog
FaCog,
FaCopy
} from 'react-icons/fa'
import * as api from '../services/api'
@ -348,6 +349,15 @@ function FileTree({ tree, selectedFiles, onFileToggle, expandedItems, onToggleEx
onClick={() => onFileToggle(fileNode, 'excel')}
/>
</Tooltip>
<Tooltip label="Copy file path">
<IconButton
size="xs"
icon={<FaCopy />}
colorScheme="purple"
variant="outline"
onClick={() => onFileToggle(fileNode, 'copy')}
/>
</Tooltip>
</VStack>
</HStack>
</CardBody>
@ -457,6 +467,40 @@ export default function CsvFileBrowser() {
duration: 3000
})
}
} else if (action === 'copy') {
// Copy path to clipboard
try {
await navigator.clipboard.writeText(fileNode.path)
toast({
title: '📋 Path copied',
description: `File path copied to clipboard`,
status: 'success',
duration: 2000
})
} catch (error) {
// Fallback for older browsers
try {
const textArea = document.createElement('textarea')
textArea.value = fileNode.path
document.body.appendChild(textArea)
textArea.select()
document.execCommand('copy')
document.body.removeChild(textArea)
toast({
title: '📋 Path copied',
description: `File path copied to clipboard`,
status: 'success',
duration: 2000
})
} catch (fallbackError) {
toast({
title: '❌ Failed to copy path',
description: 'Clipboard access not available',
status: 'error',
duration: 3000
})
}
}
} else {
// Toggle selection
const newSelected = new Set(selectedFiles)
@ -469,6 +513,56 @@ export default function CsvFileBrowser() {
}
}
// Copy selected file paths
const copySelectedPaths = async () => {
if (selectedFiles.size === 0) {
toast({
title: '⚠️ No files selected',
description: 'Please select files to copy their paths',
status: 'warning',
duration: 2000
})
return
}
try {
const filePaths = Array.from(selectedFiles)
const pathsText = filePaths.join('\n')
await navigator.clipboard.writeText(pathsText)
toast({
title: '📋 Paths copied',
description: `${filePaths.length} file path(s) copied to clipboard`,
status: 'success',
duration: 2000
})
} catch (error) {
// Fallback for older browsers
try {
const filePaths = Array.from(selectedFiles)
const pathsText = filePaths.join('\n')
const textArea = document.createElement('textarea')
textArea.value = pathsText
document.body.appendChild(textArea)
textArea.select()
document.execCommand('copy')
document.body.removeChild(textArea)
toast({
title: '📋 Paths copied',
description: `${filePaths.length} file path(s) copied to clipboard`,
status: 'success',
duration: 2000
})
} catch (fallbackError) {
toast({
title: '❌ Failed to copy paths',
description: 'Clipboard access not available',
status: 'error',
duration: 3000
})
}
}
}
// Launch PlotJuggler with selected files
const launchSelectedFiles = async () => {
if (selectedFiles.size === 0) {
@ -692,6 +786,14 @@ export default function CsvFileBrowser() {
>
Open in PlotJuggler
</Button>
<Button
leftIcon={<FaCopy />}
colorScheme="purple"
variant="outline"
onClick={copySelectedPaths}
>
Copy Paths
</Button>
<Button
variant="outline"
onClick={() => setSelectedFiles(new Set())}

View File

@ -3026,13 +3026,14 @@ def launch_plotjuggler_streamer():
# Launch PlotJuggler with UDP streamer parameters
import subprocess
cmd = [
plotjuggler_path,
"-n", # no recent files menu
"--start_streamer", "UDP streamer"
"--start_streamer",
"UDP streamer",
]
subprocess.Popen(cmd, shell=True)
return jsonify(

View File

@ -9,5 +9,6 @@
]
},
"auto_recovery_enabled": true,
"last_update": "2025-08-15T20:22:39.890817"
"last_update": "2025-08-15T20:23:13.340246",
"plotjuggler_path": "C:\\Program Files\\PlotJuggler\\plotjuggler.exe"
}