Skip to content

fix: resolve remaining PR 496 review issues#501

Closed
jeffscottward wants to merge 1 commit intoRunMaestro:mainfrom
jeffscottward:chore/fix-pr496-manual-issues
Closed

fix: resolve remaining PR 496 review issues#501
jeffscottward wants to merge 1 commit intoRunMaestro:mainfrom
jeffscottward:chore/fix-pr496-manual-issues

Conversation

@jeffscottward
Copy link
Contributor

@jeffscottward jeffscottward commented Mar 3, 2026

Summary

  • tighten CsvTableRenderer numeric detection to avoid malformed false positives in numeric alignment
  • make CsvTableRenderer highlight segment keys collision-safe

Verification

  • npx react-doctor . --verbose --no-lint --no-dead-code --offline (uncommitted changes scope)
  • task list/report generated on Desktop and reviewed

Note: task list file was created locally for tracking and not committed.

Summary by CodeRabbit

  • Bug Fixes

    • Fixed an issue where highlighting of duplicate text in CSV cells was not working correctly, now ensuring all matching substrings are properly marked and visible.
  • Improvements

    • Enhanced numeric format recognition in CSV table display to support a wider range of financial and mathematical notations, including currency symbols, parenthesized negatives, thousands separators, and percentage values.

@coderabbitai
Copy link

coderabbitai bot commented Mar 3, 2026

📝 Walkthrough

Walkthrough

Enhanced numeric value detection in a CSV table renderer component to support additional numeric formats including negative signs, currency symbols, thousands separators, and parenthesized negatives. Fixed key generation in match highlighting to ensure uniqueness by incorporating both offset and index values.

Changes

Cohort / File(s) Summary
Numeric Format Detection & Key Generation
src/renderer/components/CsvTableRenderer.tsx
Expanded isNumericValue function to recognize additional numeric formats (negatives, currency symbols, thousands separators, decimals, percentages, parenthesized negatives). Fixed highlightMatches key generation to combine offset and index for unique keys when identical substrings appear in different positions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title references fixing issues from PR 496 but lacks specificity about the actual changes (numeric detection and key collision safety in CsvTableRenderer). Consider a more descriptive title like 'fix: improve CsvTableRenderer numeric detection and highlight key generation' to better convey the specific changes.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/renderer/components/CsvTableRenderer.tsx`:
- Around line 85-87: The isNumeric regex correctly identifies parenthesized
negatives like "(123)" and "($45.67)" but compareValues currently just strips
"()" instead of converting them to negative numbers; update the numeric
normalization in compareValues (or the shared parsing helper used by
compareValues) to detect values that start with "(" and end with ")" and, after
removing surrounding parentheses, prepend a "-" before removing currency
symbols/commas and parsing so "(123)" and "($45.67)" parse as -123 and -45.67
respectively; keep existing handling for $ , and % and ensure percent and
negative signs are handled consistently.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 85d0fad and c20ed24.

📒 Files selected for processing (1)
  • src/renderer/components/CsvTableRenderer.tsx

Comment on lines +85 to +87
return /^(?:-?\$?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?%?|\(\$?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?\)%?)$/.test(
trimmed
);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n src/renderer/components/CsvTableRenderer.tsx | head -200

Repository: RunMaestro/Maestro

Length of output: 6628


🏁 Script executed:

# Verify the logic issue with a quick trace through compareValues
cat -n src/renderer/components/CsvTableRenderer.tsx | sed -n '120,140p'

Repository: RunMaestro/Maestro

Length of output: 859


🏁 Script executed:

# Double-check the indentation style to ensure it matches the guidelines
head -20 src/renderer/components/CsvTableRenderer.tsx | cat -A

Repository: RunMaestro/Maestro

Length of output: 545


🏁 Script executed:

# Verify the exact regex pattern at lines 85-87 matches parenthesized values
sed -n '85,87p' src/renderer/components/CsvTableRenderer.tsx | cat -A

Repository: RunMaestro/Maestro

Length of output: 194


Parenthesized negatives are detected but sorted with the wrong sign

Line 85 now classifies values like (123) and ($45.67) as numeric, but compareValues (lines 130–131) strips () without converting to negative, so these values sort as positive numbers.

Proposed fix
 function isNumericValue(value: string): boolean {
 	const trimmed = value.trim();
 	if (trimmed === '') return false;
 	// Match: optional currency/sign prefix, digits with optional commas, optional decimal, optional suffix
 	return /^(?:-?\$?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?%?|\(\$?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?\)%?)$/.test(
 		trimmed
 	);
 }
+
+function parseNumericValue(value: string): number | null {
+	const trimmed = value.trim();
+	if (!isNumericValue(trimmed)) return null;
+
+	const isParenNegative = /^\(.*\)$/.test(trimmed);
+	const normalized = trimmed.replace(/[,$%()]/g, '');
+	const num = Number(normalized);
+	if (Number.isNaN(num)) return null;
+
+	return isParenNegative ? -num : num;
+}
 
 function compareValues(a: string, b: string, direction: SortDirection): number {
 	const aVal = a.trim();
 	const bVal = b.trim();
@@
-	const aNum = parseFloat(aVal.replace(/[,$%()]/g, ''));
-	const bNum = parseFloat(bVal.replace(/[,$%()]/g, ''));
-
-	if (!isNaN(aNum) && !isNaN(bNum)) {
+	const aNum = parseNumericValue(aVal);
+	const bNum = parseNumericValue(bVal);
+	if (aNum !== null && bNum !== null) {
 		return direction === 'asc' ? aNum - bNum : bNum - aNum;
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return /^(?:-?\$?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?%?|\(\$?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?\)%?)$/.test(
trimmed
);
function isNumericValue(value: string): boolean {
const trimmed = value.trim();
if (trimmed === '') return false;
// Match: optional currency/sign prefix, digits with optional commas, optional decimal, optional suffix
return /^(?:-?\$?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?%?|\(\$?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?\)%?)$/.test(
trimmed
);
}
function parseNumericValue(value: string): number | null {
const trimmed = value.trim();
if (!isNumericValue(trimmed)) return null;
const isParenNegative = /^\(.*\)$/.test(trimmed);
const normalized = trimmed.replace(/[,$%()]/g, '');
const num = Number(normalized);
if (Number.isNaN(num)) return null;
return isParenNegative ? -num : num;
}
function compareValues(a: string, b: string, direction: SortDirection): number {
const aVal = a.trim();
const bVal = b.trim();
const aNum = parseNumericValue(aVal);
const bNum = parseNumericValue(bVal);
if (aNum !== null && bNum !== null) {
return direction === 'asc' ? aNum - bNum : bNum - aNum;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/components/CsvTableRenderer.tsx` around lines 85 - 87, The
isNumeric regex correctly identifies parenthesized negatives like "(123)" and
"($45.67)" but compareValues currently just strips "()" instead of converting
them to negative numbers; update the numeric normalization in compareValues (or
the shared parsing helper used by compareValues) to detect values that start
with "(" and end with ")" and, after removing surrounding parentheses, prepend a
"-" before removing currency symbols/commas and parsing so "(123)" and
"($45.67)" parse as -123 and -45.67 respectively; keep existing handling for $ ,
and % and ensure percent and negative signs are handled consistently.

@greptile-apps
Copy link

greptile-apps bot commented Mar 3, 2026

Greptile Summary

This PR contains two small but correct fixes to CsvTableRenderer.tsx, following up on PR #496 review feedback.

  • Numeric detection tightening: The isNumericValue regex is replaced with a stricter version that enforces proper comma-grouping (\d{1,3}(?:,\d{3})+) so strings like 1,2, --,,123, or bare punctuation are no longer false-positives for numeric column alignment. Both plain-digit and accounting-negative (…) forms are handled, including optional $ prefix, .decimal, and % suffix.
  • React key collision fix: highlightMatches used the running character offset as the React key. When a match appears at the very start of the text, split produces a leading empty string with offset = 0 and the first match also has offset = 0, causing a duplicate-key React warning. The fix appends -${index} to make every key unique.

One minor observation: the running comment still claims the offset "guarantee[s] uniqueness," which is inaccurate after the fix — it is index that provides the uniqueness guarantee, and using index directly as the key would be simpler and equally correct.

Confidence Score: 4/5

  • This PR is safe to merge — both changes are targeted, correct, and reduce pre-existing bugs without introducing regressions.
  • The regex tightening is a strict improvement (rejects malformed strings the old regex accepted, covers all realistic numeric/financial formats) and the key-collision fix correctly eliminates a duplicate React key. No logic regressions are apparent. One point deducted for the stale comment and slightly over-engineered compound key, which could cause mild future confusion.
  • No files require special attention.

Important Files Changed

Filename Overview
src/renderer/components/CsvTableRenderer.tsx Two targeted fixes: tightened isNumericValue regex to enforce proper comma-grouping and reject malformed strings; and replaced bare numeric offset key with compound ${offset}-${index} key in highlightMatches to prevent React duplicate-key warnings when a match starts at position 0.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["isNumericValue(value)"] --> B{trimmed === ''}
    B -- Yes --> C[return false]
    B -- No --> D{Match new regex}

    D -- "Positive form\n-?$? digit-block .decimal? %?" --> E["e.g. 1234, $1,234.56, -1,234%"]
    D -- "Accounting negative\n($? digit-block .decimal?) %?" --> F["e.g. (1,234.56), ($500)"]
    D -- No match --> G[return false]

    E --> H[return true]
    F --> H

    subgraph "digit-block alternatives"
        I["\\d+ (plain digits, no commas)"]
        J["\\d{1,3}(?:,\\d{3})+ (proper comma grouping)"]
    end

    D -.uses.-> I
    D -.uses.-> J
Loading

Last reviewed commit: c20ed24

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

1 file reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines 151 to +155
// Use running character offset as key to guarantee uniqueness across
// identical substrings appearing at different positions.
let offset = 0;
return parts.map((part) => {
const key = offset;
return parts.map((part, index) => {
const key = `${offset}-${index}`;
Copy link

Choose a reason for hiding this comment

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

Stale comment + overly complex key

The comment at line 151–152 still says the offset alone "guarantee[s] uniqueness", but the whole reason this bug existed is that offset was not unique — the empty string preceding the first match and the match itself both had offset = 0, causing the duplicate key.

Since .map((part, index) => …) already gives you a unique index per slot, you can simplify the key to just index and update the comment accordingly:

Suggested change
// Use running character offset as key to guarantee uniqueness across
// identical substrings appearing at different positions.
let offset = 0;
return parts.map((part) => {
const key = offset;
return parts.map((part, index) => {
const key = `${offset}-${index}`;
// index is unique within this map call, so use it directly as the React key.
return parts.map((part, index) => {
const key = index;
offset += part.length;

The compound ${offset}-${index} is not incorrect, but it implies the offset contributes uniqueness when it doesn't — only index does.

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.

1 participant