Graph Panel widget: add a context menu#396
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a context menu to the Graph Panel widget to support common figure/data export workflows (addressing Issue #386) and improves robustness of CSV export behavior.
Changes:
- Adds a right-click context menu to the graph panel with zoom/reset actions.
- Adds export actions for copying the plot to clipboard and exporting plot images in multiple formats.
- Wraps CSV export in
try/catch/finallyto ensure the progress message is cleaned up even on failure.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (4)
src/renderer/src/components/OpenCOR.vue:205
- This uses a string key in
provide('progressMessage', ...). Elsewhere (e.g.DialogStateKeyincomponents/dialogs/BaseDialog.vue) aSymbolkey is used to avoid collisions and improve typing. Consider exporting anInjectionKey<IProgressMessage>(Symbol) and using it for bothprovide()andinject().
vue.provide('progressMessage', {
show,
update,
hide
});
src/renderer/src/components/widgets/GraphPanelWidget.vue:240
copyToClipboard()only logs failures to the console. Since clipboard APIs are frequently unavailable/permission-gated (especially for image clipboard writes), users may think the feature is broken. Consider surfacing an in-app error (toast/dialog) and/or feature-detectingnavigator.clipboard/ClipboardItemto provide a clearer message when unsupported.
async function copyToClipboard(): Promise<void> {
if (!mainDiv.value) {
return;
}
try {
const imageData = await Plotly.toImage(mainDiv.value, {
format: 'png',
width: mainDiv.value.clientWidth,
height: mainDiv.value.clientHeight
});
const binaryData = atob(imageData.split(',')[1]);
const array = Uint8Array.from(binaryData, (c) => c.charCodeAt(0));
await navigator.clipboard.write([
new ClipboardItem({
'image/png': new Blob([array], { type: 'image/png' })
})
]);
} catch (error: unknown) {
console.error('Failed to copy to clipboard:', common.formatError(error));
}
src/renderer/src/components/widgets/GraphPanelWidget.vue:32
xValue/yValueare now part ofIGraphPanelPlotTrace, but the plot rendering later spreadstracedirectly into the Plotly trace object. Plotly doesn't havexValue/yValuetrace attributes, so this will typically generate “unknown attribute” warnings (and may be rejected by stricter validation). Consider keeping these metadata fields separate from the object passed to Plotly (e.g., strip them out when building Plotly traces).
export interface IGraphPanelPlotTrace {
name: string;
xValue: string;
x: Float64Array;
yValue: string;
y: Float64Array;
color: string;
zorder?: number;
src/renderer/src/components/widgets/GraphPanelWidget.vue:74
- This
inject('progressMessage')relies on a string key. If you switch the provider to aSymbol/InjectionKey(as suggested in OpenCOR.vue), update the injection here accordingly to keep typing and avoid key collisions.
const progressMessage = vue.inject<IProgressMessage>('progressMessage');
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Fixes #386.