Skip to content

Conversation

jnumainville
Copy link
Contributor

@jnumainville jnumainville commented Aug 27, 2025

Adds new actions when hovering over console history items: copy, rerun, and a contextual help with timing (from the same source as the extant time in our command history but formatted differently to meet spec) as well as new server timing.

Full support is dependent on adding server timing to console history from core. That PR is not up yet but just running this PR will just not show that time.

@jnumainville jnumainville requested a review from Copilot August 27, 2025 21:25
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds hover actions to console history items, including copy, rerun functionality, and a contextual help tooltip displaying execution timing information. The implementation supports both client-side execution time and server query time (when available from the backend).

  • Adds hover actions (copy, rerun, info tooltip) to console history items
  • Implements timing display functionality with support for millisecond and nanosecond conversions
  • Extends console history data structures to include server timing information

Reviewed Changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
ConsoleHistoryTypes.tsx Adds server timing fields to the action item interface
ConsoleHistoryItemTooltip.tsx New component for displaying execution timing information in a contextual help tooltip
ConsoleHistoryItemTooltip.test.tsx Test suite for the tooltip component and time formatting utility
ConsoleHistoryItemActions.tsx New component containing copy, rerun, and info actions that appear on hover
ConsoleHistoryItem.tsx Integrates action buttons and hover state management
ConsoleHistoryItem.scss Styles for hover effects and action button positioning
ConsoleHistory.tsx Passes command submit handler to history items
ConsoleHistory.scss Additional tooltip styling
CommandHistoryStorage.ts Extends storage interface to include server timing
Console.tsx Updates console to handle and pass server timing data

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Copy link

codecov bot commented Aug 28, 2025

Codecov Report

❌ Patch coverage is 86.74699% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 44.67%. Comparing base (21c06c0) to head (6122e9c).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
...console/src/console-history/ConsoleHistoryItem.tsx 30.00% 7 Missing ⚠️
packages/console/src/Console.tsx 0.00% 2 Missing ⚠️
.../src/console-history/ConsoleHistoryItemActions.tsx 86.66% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2526      +/-   ##
==========================================
+ Coverage   44.61%   44.67%   +0.05%     
==========================================
  Files         764      766       +2     
  Lines       42800    42900     +100     
  Branches    10766    10788      +22     
==========================================
+ Hits        19096    19165      +69     
- Misses      23693    23724      +31     
  Partials       11       11              
Flag Coverage Δ
unit 44.67% <86.74%> (+0.05%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jnumainville jnumainville requested a review from mofojed August 28, 2025 21:28
@jnumainville jnumainville marked this pull request as ready for review August 28, 2025 21:28
}

.console-history-actions {
z-index: 1000;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't have the z-index so high. In bootstraps _variables.scss, they define a bunch of $zindex-* variables, and $zindex-dropdown is 1000, so this could in theory conflict with that. Probably should only set it to 100 at most.
That being said - why do we need to set this anyway?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed - this was just leftover from some experimentation I was doing with the hover behavior

Comment on lines 101 to 102
onMouseOver={() => this.setState({ isHovered: true })}
onMouseOut={() => this.setState({ isHovered: false })}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need this isHovered state at all - instead just key off the :hover CSS class.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

padding: $spacer-1;
}

.console-history-item-command-hovered {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need to do this yourself, you can just use the :hover pseudo-class:

Suggested change
.console-history-item-command-hovered {
.console-history-item-command:hover {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I originally had it with the pseudo-class, but the behavior is buggy. When I click on the contextual help button, the hover stops, and the contextual help popup moves to the top left corner of the screen (seemingly because the contextual help button is gone). Is there a good way to use the pseudo class that keeps it hovered after clicking on the contextual help?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Target the :hover, then when the tooltip is shown add another class that can also be targeted

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines 24 to 42
const lineCount = command.split('\n').length;
const classes = ['console-history-actions'];

if (lineCount === 1) {
if (firstItem) {
// first single items are pushed down so that they are visible
// this should be higher priority than lastItem
classes.push('console-history-first-single-line');
} else if (lastItem) {
// last single items are pushed up to prevent layout shifts
classes.push('console-history-last-single-line');
} else {
classes.push('console-history-single-line');
}
} else if (lineCount === 2) {
classes.push('console-history-two-lines');
}
return classes.join(' ');
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need the firstItem or lastItem properties at all - you can do this all with CSS!
Take a look at the :first-child and :last-child pseudo-classes: https://developer.mozilla.org/en-US/docs/Web/CSS/:first-child

Then in CSS instead of doing .console-history-last-single-line, you would do .console-command-result:first-child (or even .console-command-result:first-child .console-history-item-command if you want to select an inner element within that child).

Then we don't need to manually track the classes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a really cool feature - how should I properly target only first and last when there is one line of text?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.console-command-result:first-child .console-history-actions-line-1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

* @param conversion The conversion type ('ms' or 'ns')
* @returns A string representing the time difference, or null if invalid.
*/
export const getTimeString = (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use this function from CommandHistoryItemTooltip.tsx as well for consistency.

Copy link
Contributor Author

@jnumainville jnumainville Sep 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like the CommandHistoryItemTooltip.tsx one has a couple key differences:

  1. If the delta is less than 1 second it just returns "<1s"
  2. Possibly has hours, minutes, and seconds, like "1h 3m 23s"

I don't want to remove that formatting completely without verifying how we want to unify this, as the formats are different enough where one isn't inherently better than the other I think. Thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the ticket DH-19382:

Label as “Execution time: 1.02s” - round to two decimals, and add appropriate units. Note time could be seconds to hours, so display units accordingly.

@dsmmcken if we had a time that was over an hour, what format should it display in?

  1. 1h 3m 23s (rounded to the second)
  2. 1h 3m 23.02s (larger units split out, but seconds rounded to two decimal places)
  3. 1.05h (round to two decimal places of the largest unit
  4. ???

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if greater than 1 hour, no decimals: 1h 2m 32s

if less than an hour, 1 decimal: 2m 32.1s

if less than a minute, 2 decimals: 32.02s

I would say precision matter less the higher the scale goes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

modified both to use new format

@jnumainville jnumainville requested a review from mofojed September 4, 2025 22:18
onMouseOver={() => this.setState({ isHovered: true })}
onMouseOut={() => this.setState({ isHovered: false })}
>
<div className={this.consoleHistoryItemClasses()}>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just use classNames package instead of writing your own function.

Suggested change
<div className={this.consoleHistoryItemClasses()}>
<div className={classNames('console-history-item-command', { 'console-history-item-command-tooltip-active': isTootipVisible })>

Comment on lines +132 to +138
if (time < 60) {
return `${seconds.toFixed(2)}s`;
}
if (time < 3600) {
return `${mins}m ${seconds.toFixed(1)}s`;
}
return `${hours}h ${mins}m ${seconds}s`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I would've flipped this logic around to check if there was anything in hours or minutes rather than checking against time again. You've already dissected time, why not use the components you have? E.g.

if (hours > 0) {
  return `${hours}h ${mins}m ${seconds}s`;
}
if (minutes > 0) {
  return `${mins}m ${seconds.toFixed(1)}s`;
}
return `${seconds.toFixed(2)}s`;

Copy link
Member

@mofojed mofojed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops, meant to request changes for the classNames suggestion

@mofojed
Copy link
Member

mofojed commented Sep 10, 2025

Let's not merge until the API gets merged: deephaven/deephaven-core#7145

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants