-
Notifications
You must be signed in to change notification settings - Fork 75
feat: can multi-select deployments when pressing shift #1994
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: can multi-select deployments when pressing shift #1994
Conversation
WalkthroughAdds Shift-key range selection to the deployments list: tracks global Shift release, maintains an interval selection anchor and last interval selection dseqs, computes and applies multi-row selections (deduplicated), and threads shift/hover state between Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor U as User
participant R as DeploymentListRow
participant L as DeploymentList
rect rgba(235,245,255,0.5)
note over U,L: Global Shift tracking
U-->>L: keydown/keyup (Shift)
L->>L: on keyup(SHIFT_KEY) reset interval selection state
end
rect rgba(235,255,235,0.5)
note over U,L: Hover tracking
U->>R: mouseenter row
R->>L: onMouseEnter(dseq)
L->>L: set hovered state (isHighlighted)
end
rect rgba(255,250,235,0.6)
note over U,L: Selection flow
U->>R: click checkbox (with/without Shift)
R->>L: onSelectDeployment(checked, dseq, event.shiftKey)
alt Shift pressed and anchor exists
L->>L: compute range via indexOfDseq/isBetweenDseqs on current page
L->>L: changeMultipleSelection -> dedupe via uniq and apply selections
else No Shift
L->>L: toggleSingleSelection -> set anchor / select single
end
L-->>R: update isHighlighted for rows in selection/range
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (1)
apps/deploy-web/src/components/deployments/DeploymentList.tsx (1)
207-217
: Remove the redundant index check.Line 214 checks
dseqIndex !== undefined
, but this check is redundant becauseisBetweenDseqs
already validates all indices (once the bug inisBetweenDseqs
is fixed to check for-1
).Apply this diff to simplify the logic:
const isRowHighlightedForMultipleSelection = useCallback( (dseq: string) => { if (!isShiftPressed || !hoveredDelpoymentDseq || !lastSelectedDeploymentDseq) { return false; } - const dseqIndex = currentPageDeployments?.findIndex(d => d.dseq === dseq); - return dseqIndex !== undefined && isBetweenDseqs(dseq, hoveredDelpoymentDseq, lastSelectedDeploymentDseq); + return isBetweenDseqs(dseq, hoveredDelpoymentDseq, lastSelectedDeploymentDseq); }, [isShiftPressed, hoveredDelpoymentDseq, lastSelectedDeploymentDseq, currentPageDeployments, isBetweenDseqs] );
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/deploy-web/src/components/deployments/DeploymentList.tsx
(6 hunks)apps/deploy-web/src/components/deployments/DeploymentListRow.tsx
(5 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
Never use type any or cast to type any. Always define the proper TypeScript types.
Files:
apps/deploy-web/src/components/deployments/DeploymentListRow.tsx
apps/deploy-web/src/components/deployments/DeploymentList.tsx
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{js,ts,tsx}
: Never use deprecated methods from libraries.
Don't add unnecessary comments to the code
Files:
apps/deploy-web/src/components/deployments/DeploymentListRow.tsx
apps/deploy-web/src/components/deployments/DeploymentList.tsx
🧬 Code graph analysis (1)
apps/deploy-web/src/components/deployments/DeploymentListRow.tsx (2)
apps/deploy-web/src/types/provider.ts (1)
ApiProviderList
(185-273)apps/provider-console/src/utils/styleUtils.ts (1)
cn
(4-6)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: validate / validate-app
- GitHub Check: test-build
🔇 Additional comments (9)
apps/deploy-web/src/components/deployments/DeploymentList.tsx (4)
2-2
: LGTM!The imports for
useCallback
anduniq
are correct and align with the new range-selection feature.Also applies to: 21-21
133-146
: LGTM!The range selection logic is well-implemented:
- Correctly uses Shift key state to determine range vs. single selection
- Updates
lastSelectedDeploymentDseq
only when Shift is not pressed, allowing sequential range selections- Uses
uniq
to deduplicate selected dseqsNote: This logic depends on the
isBetweenDseqs
helper being fixed (see previous comment).
180-201
: LGTM!The global Shift key tracking is correctly implemented:
- Proper event listener setup and cleanup
- Correctly updates state on keydown/keyup
- Standard pattern for tracking key state
364-365
: LGTM!The props
onMouseEnter
andisHighlighted
are correctly passed toDeploymentListRow
, matching the updated component signature.apps/deploy-web/src/components/deployments/DeploymentListRow.tsx (5)
16-16
: LGTM!The
cn
utility import is correct and aligns with the new conditional row highlighting feature.
54-55
: LGTM!The Props interface updates are correct:
onSelectDeployment
now acceptseventShiftPressed
to support Shift-based range selectionrefreshDeployments
type improved fromany
to() => void
(aligns with coding guidelines)- New
onMouseEnter
andisHighlighted
props support hover tracking and row highlightingAlso applies to: 58-58, 60-60
63-72
: LGTM!The component destructuring correctly includes the new
onMouseEnter
andisHighlighted
props.
183-190
: LGTM!The
TableRow
rendering correctly implements hover tracking and conditional highlighting:
cn
utility properly applies conditional background class whenisHighlighted
is trueonMouseEnter
handler correctly uses optional chaining and passesdeployment.dseq
147-147
: LGTM!The event handler updates are correct:
- Checkbox
onClick
correctly captures and passesevent.shiftKey
to support range selectiononCloseDeployment
correctly passesfalse
foreventShiftPressed
when unselectingAlso applies to: 318-318
9aadf4e
to
9c45413
Compare
There was a problem hiding this 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
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/deploy-web/src/components/deployments/DeploymentList.tsx
(7 hunks)apps/deploy-web/src/components/deployments/DeploymentListRow.tsx
(5 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
Never use type any or cast to type any. Always define the proper TypeScript types.
Files:
apps/deploy-web/src/components/deployments/DeploymentList.tsx
apps/deploy-web/src/components/deployments/DeploymentListRow.tsx
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{js,ts,tsx}
: Never use deprecated methods from libraries.
Don't add unnecessary comments to the code
Files:
apps/deploy-web/src/components/deployments/DeploymentList.tsx
apps/deploy-web/src/components/deployments/DeploymentListRow.tsx
🧬 Code graph analysis (1)
apps/deploy-web/src/components/deployments/DeploymentListRow.tsx (2)
apps/deploy-web/src/types/provider.ts (1)
ApiProviderList
(185-273)apps/provider-console/src/utils/styleUtils.ts (1)
cn
(4-6)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: validate / validate-app
- GitHub Check: test-build
hey @jzsfkzm I've tested this and the logic feels a bit weird when it comes to some edge cases. I've asked ChatGPT to get me some common flow instructions below to make it more clear. wdut? Row Multiselect (Shift) — LogicOverviewWhen Shift is pressed, clicking a row selects a continuous range between the first selected row (the anchor) and the currently clicked row. This lets users select multiple consecutive rows in one action. Behavior
ExamplesExample 1 — Simple Downward Selection
Outcome: A continuous block from 2 → 5. Example 2 — Reversing Direction
Outcome: Works the same upward — direction doesn’t matter. Example 3 — Expanding, Then Contracting
Outcome: The range shrinks or grows depending on the new target, but always remains continuous from the same anchor. Example 4 — New Anchor After Normal Click
Outcome: A plain click resets both selection and anchor. Example 5 — Jumping Around
Outcome: Each Shift-click recalculates the range from the same anchor (Row 3). Example 6 — First Click is Shifted
Outcome: If Shift-click happens first, it behaves as a normal click for the initial anchor. Key Points
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed:
Length of output: 14087 @ygrishajev, I've reviewed the current implementation against the proposed specification. There are several key differences that explain the "weird" behavior you're experiencing: Critical Issues1. Shift-click is additive, not replacement ❌Current behavior: Each shift-click extends the selection setSelectedDeploymentDseqs(prev => {
return checked ? uniq(prev.concat(dseqs)) : prev.filter(x => !dseqs.includes(x));
}); Expected behavior: Each shift-click should replace the previous range Example of the problem:
2. Normal click doesn't clear existing selections ❌Current behavior: Clicking a checkbox toggles only that row Expected behavior: A normal click (without Shift) should:
Example of the problem:
3. Cannot distinguish between checking and unchecking flowsThe spec implies that normal clicks should always clear and select, but the current implementation allows unchecking by clicking an already-checked row. Need to clarify this edge case. Suggested Implementation ApproachYou'll need to track the previous shift-selected range to replace it: const [shiftSelectedDseqs, setShiftSelectedDseqs] = useState<string[]>([]);
const onSelectDeployment = (checked: boolean, dseq: string, eventShiftPressed: boolean) => {
if (eventShiftPressed && lastSelectedDeploymentDseq) {
// Compute new range
const newRange = currentPageDeployments
.filter(d => isBetweenDseqs(d.dseq, dseq, lastSelectedDeploymentDseq))
.map(d => d.dseq);
setSelectedDeploymentDseqs(prev => {
// Remove previous shift-range, add new range
const withoutPrevRange = prev.filter(x => !shiftSelectedDseqs.includes(x));
return checked ? uniq([...withoutPrevRange, ...newRange]) : withoutPrevRange;
});
// Remember this range for next shift-click
setShiftSelectedDseqs(newRange);
} else {
// Normal click: clear all and select only this row
if (checked) {
setSelectedDeploymentDseqs([dseq]);
setLastSelectedDeploymentDseq(dseq);
setShiftSelectedDseqs([]);
} else {
// Unchecking: remove only this row
setSelectedDeploymentDseqs(prev => prev.filter(x => x !== dseq));
}
}
}; Questions to Clarify
The proposed spec looks solid and aligns with standard multi-select UX patterns (similar to file managers, spreadsheets, etc.). The implementation just needs these adjustments to match the behavior. |
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed:
Length of output: 30291 @ygrishajev, I've reviewed the implementation against the specification you provided, and I've identified several deviations that likely cause the "weird edge cases" you're experiencing. Key Issues1. Normal clicks don't clear existing selection (Violates Behavior #4)Specification says: "Normal Click (no Shift): Clears any existing selection. Selects only the clicked row." Current behavior: Normal clicks add to or remove from the existing selection instead of clearing it. In setSelectedDeploymentDseqs(prev => {
return checked ? uniq(prev.concat(dseqs)) : prev.filter(x => !dseqs.includes(x));
}); This concatenates ( Example:
2. Shift-clicks extend instead of replace (Violates Behavior #3)Specification says: "Each Shift-click replaces, not extends, the previous selection range." Current behavior: Shift-clicks concatenate to existing selection using Example:
3. The
|
Action | Result |
---|---|
Click Row 3 | selectedDeploymentDseqs = [3] , anchor = 3 ✅ |
Shift+Click Row 7 | selectedDeploymentDseqs = [3,4,5,6,7] , anchor = 3 ✅ |
Shift+Click Row 5 | selectedDeploymentDseqs = [3,4,5] , anchor = 3 ✅ (replaced!) |
And Example 4:
Action | Result |
---|---|
Click Row 4 | selectedDeploymentDseqs = [4] , anchor = 4 ✅ |
Shift+Click Row 8 | selectedDeploymentDseqs = [4,5,6,7,8] , anchor = 4 ✅ |
Click Row 2 | selectedDeploymentDseqs = [2] , anchor = 2 ✅ (cleared!) |
Shift+Click Row 5 | selectedDeploymentDseqs = [2,3,4,5] , anchor = 2 ✅ |
Additional Consideration
You may also want to handle the checkbox click behavior in DeploymentListRow.tsx
(line 260):
onClick={event => {
event.stopPropagation();
onSelectDeployment?.(!checked, deployment.dseq, event.shiftKey);
}}
With the spec's behavior, clicking an already-checked checkbox should deselect only that row (without clearing others), while a normal row click should clear all and select one. You might need separate handlers for checkbox vs. row clicks, or adjust the logic to match your desired UX.
Would you like me to generate the complete updated code for both files, or would you prefer to have the team make these adjustments?
@coderabbitai what do you think of the spec provided generally? Would you consider this to be a common approach? |
Tip For best results, initiate chat on the files or code changes. @ygrishajev: Yes, absolutely! This is the standard approach for shift-click multi-select, and it's used consistently across many mature applications: Common ImplementationsFile Managers:
Email Clients:
Productivity Apps:
Design Tools:
Why It's Effective
Your Spec QualityThe specification you provided is excellent. It's:
One Additional Edge Case to ConsiderCtrl/Cmd + Click (Multi-Select):
This is optional but worth considering if users need to select non-sequential items before bulk actions (e.g., close rows 2, 5, 9, 12). Bottom line: Your spec describes industry-standard behavior. Implementing it will give users a familiar, efficient experience. The issues I identified earlier are just implementation bugs—the design itself is solid. 👍 |
9c45413
to
9d3d66b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
apps/deploy-web/src/components/deployments/DeploymentList.tsx
(6 hunks)apps/deploy-web/src/components/deployments/DeploymentListRow.tsx
(3 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
Never use type any or cast to type any. Always define the proper TypeScript types.
Files:
apps/deploy-web/src/components/deployments/DeploymentList.tsx
apps/deploy-web/src/components/deployments/DeploymentListRow.tsx
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/general.mdc)
**/*.{js,ts,tsx}
: Never use deprecated methods from libraries.
Don't add unnecessary comments to the code
Files:
apps/deploy-web/src/components/deployments/DeploymentList.tsx
apps/deploy-web/src/components/deployments/DeploymentListRow.tsx
🧬 Code graph analysis (1)
apps/deploy-web/src/components/deployments/DeploymentListRow.tsx (1)
apps/deploy-web/src/types/provider.ts (1)
ApiProviderList
(185-273)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: validate / validate-app
- GitHub Check: test-build
🔇 Additional comments (4)
apps/deploy-web/src/components/deployments/DeploymentListRow.tsx (2)
56-56
: Good type narrowing forrefreshDeployments
.Changing from
any
to() => void
improves type safety and adheres to the coding guideline prohibitingany
.As per coding guidelines.
53-53
: LGTM: Shift-key integration.The updated signature threads
eventShiftPressed
correctly, and the checkbox handler properly surfacesevent.shiftKey
to the parent for range-selection logic.Also applies to: 299-299
apps/deploy-web/src/components/deployments/DeploymentList.tsx (2)
210-222
: LGTM: Global keyup listener resets shift state.Resetting
lastIntervalSelectionDseqs
when the Shift key is released ensures that the next Shift-click starts a fresh range from the anchor. The cleanup in the return properly removes the listener.
119-147
: LGTM: Helper functions for range calculation.The
indexOfDseq
,isBetweenDseqs
, andcurrentPageDeploymentsBetween
helpers correctly compute the continuous block between two dseqs, handling bidirectional ranges (upward/downward selection). The index validation (!== -1
) is correct.
const toggleSingleSelection = (checked: boolean, dseq: string) => { | ||
setSelectedDeploymentDseqs(prev => (checked ? [...prev, dseq] : prev.filter(x => x !== dseq))); | ||
if (checked) { | ||
setIntervalSelectionAnchor(dseq); | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anchor should update on every normal click, including uncheck.
The anchor is only set when checked === true
. According to the spec, any normal (non-Shift) click should set a new anchor, even if the click unchecks the currently selected row (though with the "clear and select only clicked" behavior, this case won't occur).
This will be resolved by the fix suggested in the earlier comment (always setting the anchor in toggleSingleSelection
).
🤖 Prompt for AI Agents
In apps/deploy-web/src/components/deployments/DeploymentList.tsx around lines
149 to 154, toggleSingleSelection currently only updates the interval selection
anchor when checked is true; update it to always set the anchor on any normal
(non-Shift) click by calling setIntervalSelectionAnchor(dseq) regardless of the
checked value so the anchor reflects the most recent click, while retaining the
existing selected-deployments update logic.
Normal click should clear all selections and select only the clicked row.
The current implementation toggles: if checked
is true
, it adds the row; if false
, it removes it. According to the canonical shift-click spec (from PR comments), a normal (non-Shift) click should clear all existing selections, select only the clicked row, and set it as the new anchor.
Apply this diff to align with the spec:
const toggleSingleSelection = (checked: boolean, dseq: string) => {
- setSelectedDeploymentDseqs(prev => (checked ? [...prev, dseq] : prev.filter(x => x !== dseq)));
- if (checked) {
- setIntervalSelectionAnchor(dseq);
- }
+ setSelectedDeploymentDseqs([dseq]);
+ setIntervalSelectionAnchor(dseq);
+ setLastIntervalSelectionDseqs([]);
};
Note: This assumes the checkbox handler passes the desired selection state, not the current state. You may need to adjust the handler in DeploymentListRow.tsx
at Line 299 to pass true
instead of !checked
if you want clicks to always select (not toggle).
📝 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.
const toggleSingleSelection = (checked: boolean, dseq: string) => { | |
setSelectedDeploymentDseqs(prev => (checked ? [...prev, dseq] : prev.filter(x => x !== dseq))); | |
if (checked) { | |
setIntervalSelectionAnchor(dseq); | |
} | |
}; | |
const toggleSingleSelection = (checked: boolean, dseq: string) => { | |
setSelectedDeploymentDseqs([dseq]); | |
setIntervalSelectionAnchor(dseq); | |
setLastIntervalSelectionDseqs([]); | |
}; |
🤖 Prompt for AI Agents
In apps/deploy-web/src/components/deployments/DeploymentList.tsx around lines
149 to 154, change toggleSingleSelection so a normal (non-Shift) click clears
existing selections and selects only the clicked row: when checked is true
setSelectedDeploymentDseqs to [dseq] and setIntervalSelectionAnchor(dseq); when
checked is false clear the selection (set to []). Also verify the checkbox
handler in DeploymentListRow.tsx (around line 299) passes the intended selection
state (true for selecting) rather than toggling(!checked) if needed.
const changeMultipleSelection = (dseq: string) => { | ||
if (!intervalSelectionAnchor) { | ||
return; | ||
} | ||
|
||
const dseqsToCheck = currentPageDeploymentsBetween(dseq, intervalSelectionAnchor); | ||
const dseqsToUncheck = lastIntervalSelectionDseqs; | ||
|
||
setSelectedDeploymentDseqs(prev => { | ||
return checked ? prev.concat([dseq]) : prev.filter(x => x !== dseq); | ||
return uniq(prev.filter(x => !dseqsToUncheck.includes(x)).concat(dseqsToCheck)); | ||
}); | ||
setLastIntervalSelectionDseqs(dseqsToCheck); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shift-click should replace the entire selection with the range.
The current implementation removes the previous shift-selected range and adds the new range, but keeps any other previously selected items (via uniq(prev.filter(...).concat(...))
). According to the spec, each Shift-click should replace the entire selection with the continuous block between the anchor and the clicked row, not extend it additively.
Apply this diff to replace the entire selection:
const changeMultipleSelection = (dseq: string) => {
if (!intervalSelectionAnchor) {
return;
}
const dseqsToCheck = currentPageDeploymentsBetween(dseq, intervalSelectionAnchor);
- const dseqsToUncheck = lastIntervalSelectionDseqs;
- setSelectedDeploymentDseqs(prev => {
- return uniq(prev.filter(x => !dseqsToUncheck.includes(x)).concat(dseqsToCheck));
- });
+ setSelectedDeploymentDseqs(dseqsToCheck);
setLastIntervalSelectionDseqs(dseqsToCheck);
};
If you want to support Ctrl/Cmd+Click for non-contiguous multi-select (toggling individual items while keeping others), you'll need a separate handler that doesn't clear selections.
📝 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.
const changeMultipleSelection = (dseq: string) => { | |
if (!intervalSelectionAnchor) { | |
return; | |
} | |
const dseqsToCheck = currentPageDeploymentsBetween(dseq, intervalSelectionAnchor); | |
const dseqsToUncheck = lastIntervalSelectionDseqs; | |
setSelectedDeploymentDseqs(prev => { | |
return checked ? prev.concat([dseq]) : prev.filter(x => x !== dseq); | |
return uniq(prev.filter(x => !dseqsToUncheck.includes(x)).concat(dseqsToCheck)); | |
}); | |
setLastIntervalSelectionDseqs(dseqsToCheck); | |
}; | |
const changeMultipleSelection = (dseq: string) => { | |
if (!intervalSelectionAnchor) { | |
return; | |
} | |
const dseqsToCheck = currentPageDeploymentsBetween(dseq, intervalSelectionAnchor); | |
setSelectedDeploymentDseqs(dseqsToCheck); | |
setLastIntervalSelectionDseqs(dseqsToCheck); | |
}; |
🤖 Prompt for AI Agents
In apps/deploy-web/src/components/deployments/DeploymentList.tsx around lines
156-168, the shift-click handler currently removes the previous shift-selected
range and adds the new range on top of any other selected items; change it so
Shift-click replaces the entire selection with the continuous block between the
anchor and clicked row by calling setSelectedDeploymentDseqs(dseqsToCheck)
(i.e., overwrite previous selection) and then
setLastIntervalSelectionDseqs(dseqsToCheck); keep any Ctrl/Cmd+Click
non-contiguous toggling behavior in a separate handler if needed.
Add fallback when shift-range is empty.
When intervalSelectionAnchor
points to a deployment on a different page (after paging/filtering), currentPageDeploymentsBetween
returns an empty array, and setSelectedDeploymentDseqs
is called with an empty array—clearing all selections instead of at least selecting the clicked row.
Apply this diff to ensure the clicked row is always selected:
const changeMultipleSelection = (dseq: string) => {
if (!intervalSelectionAnchor) {
return;
}
const dseqsToCheck = currentPageDeploymentsBetween(dseq, intervalSelectionAnchor);
- const dseqsToUncheck = lastIntervalSelectionDseqs;
- setSelectedDeploymentDseqs(prev => {
- return uniq(prev.filter(x => !dseqsToUncheck.includes(x)).concat(dseqsToCheck));
- });
+ const finalSelection = dseqsToCheck.length > 0 ? dseqsToCheck : [dseq];
+ setSelectedDeploymentDseqs(finalSelection);
- setLastIntervalSelectionDseqs(dseqsToCheck);
+ setLastIntervalSelectionDseqs(finalSelection);
};
Based on past review comments.
📝 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.
const changeMultipleSelection = (dseq: string) => { | |
if (!intervalSelectionAnchor) { | |
return; | |
} | |
const dseqsToCheck = currentPageDeploymentsBetween(dseq, intervalSelectionAnchor); | |
const dseqsToUncheck = lastIntervalSelectionDseqs; | |
setSelectedDeploymentDseqs(prev => { | |
return checked ? prev.concat([dseq]) : prev.filter(x => x !== dseq); | |
return uniq(prev.filter(x => !dseqsToUncheck.includes(x)).concat(dseqsToCheck)); | |
}); | |
setLastIntervalSelectionDseqs(dseqsToCheck); | |
}; | |
const changeMultipleSelection = (dseq: string) => { | |
if (!intervalSelectionAnchor) { | |
return; | |
} | |
const dseqsToCheck = currentPageDeploymentsBetween(dseq, intervalSelectionAnchor); | |
const finalSelection = dseqsToCheck.length > 0 ? dseqsToCheck : [dseq]; | |
setSelectedDeploymentDseqs(finalSelection); | |
setLastIntervalSelectionDseqs(finalSelection); | |
}; |
🤖 Prompt for AI Agents
In apps/deploy-web/src/components/deployments/DeploymentList.tsx around lines
156 to 168, the shift-range selection clears all selections when
currentPageDeploymentsBetween returns an empty array; change the handler so if
dseqsToCheck is empty (anchor on another page) it falls back to selecting the
clicked dseq itself (i.e., set dseqsToCheck = [dseq] before updating state),
then proceed to remove lastIntervalSelectionDseqs from previous selection and
add dseqsToCheck, and finally setLastIntervalSelectionDseqs to the chosen
dseqsToCheck.
@ygrishajev I see why you said it's weird. Re-selecting the same interval, or an overlapping interval indeed was behaving in unexpected ways. I changed it a bit, now I think it's better, will you check too? |
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed:
Length of output: 29637 @jzsfkzm, great work on the updates! I've reviewed the changes and can confirm you've made solid progress. Let me break down what's working now and what might need clarification: ✅ Fixed Issues1. Shift-click now replaces ranges correctlyThe setSelectedDeploymentDseqs(prev => {
return uniq(prev.filter(x => !dseqsToUncheck.includes(x)).concat(dseqsToCheck));
}); Example validation (from the spec):
This now matches the expected behavior perfectly! 2. Tracking shift-selected rangesYou're correctly tracking
|
closes #1982
Summary by CodeRabbit
New Features
Enhancements