feat: Add file path copying functionality to CSV File Browser and update PlotJuggler launch command
This commit is contained in:
parent
3a830fe100
commit
02b622cb20
|
@ -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())}
|
||||
|
|
7
main.py
7
main.py
|
@ -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(
|
||||
|
|
|
@ -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"
|
||||
}
|
Loading…
Reference in New Issue