mirror of
https://github.com/Aider-AI/aider.git
synced 2025-05-31 09:44:59 +00:00
feat: Dynamically adjust cost scale and ticks based on visible entries
This commit is contained in:
parent
119fbc995c
commit
23f182aab3
1 changed files with 132 additions and 63 deletions
|
@ -34,6 +34,10 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
if (currentMode === 'select') {
|
||||
updateSelectAllCheckboxState();
|
||||
}
|
||||
|
||||
// Update cost bars and ticks since visible rows may have changed
|
||||
updateCostBars();
|
||||
updateCostTicks();
|
||||
}
|
||||
|
||||
function getVisibleMainRows() {
|
||||
|
@ -89,7 +93,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
// Get the first header cell (for the toggle/checkbox column)
|
||||
const firstHeaderCell = document.querySelector('table thead th:first-child');
|
||||
|
||||
|
||||
// Show/hide header checkbox based on mode
|
||||
selectAllCheckbox.style.display = mode === 'select' ? 'inline-block' : 'none';
|
||||
|
||||
|
@ -193,6 +196,10 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
|
||||
// Update the select-all checkbox state after updating the view
|
||||
updateSelectAllCheckboxState();
|
||||
|
||||
// Update cost bars and ticks since visible/selected rows may have changed
|
||||
updateCostBars();
|
||||
updateCostTicks();
|
||||
}
|
||||
|
||||
|
||||
|
@ -209,75 +216,127 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
}
|
||||
});
|
||||
|
||||
// Process cost bars
|
||||
const costBars = document.querySelectorAll('.cost-bar');
|
||||
const MAX_DISPLAY_COST = 50; // $50 limit for visual display
|
||||
|
||||
costBars.forEach(bar => {
|
||||
const cost = parseFloat(bar.dataset.cost);
|
||||
const maxCost = parseFloat(bar.dataset.maxCost);
|
||||
|
||||
if (cost > 0 && maxCost > 0) {
|
||||
// Use $50 as the max for display purposes
|
||||
const displayMaxCost = Math.min(MAX_DISPLAY_COST, maxCost);
|
||||
// Calculate percentage based on the display max
|
||||
const percent = Math.min(cost, displayMaxCost) / displayMaxCost * 100;
|
||||
// Clamp percentage between 0 and 100
|
||||
bar.style.width = Math.max(0, Math.min(100, percent)) + '%';
|
||||
|
||||
// Mark bars that exceed the limit
|
||||
if (cost > MAX_DISPLAY_COST) {
|
||||
// Create a darker section at the end with diagonal stripes
|
||||
const darkSection = document.createElement('div');
|
||||
darkSection.className = 'bar-viz';
|
||||
darkSection.style.width = '15%'; // From 85% to 100%
|
||||
darkSection.style.left = '85%';
|
||||
darkSection.style.backgroundColor = 'rgba(13, 110, 253, 0.6)'; // Darker blue
|
||||
darkSection.style.borderRight = '1px solid rgba(13, 110, 253, 0.8)';
|
||||
darkSection.style.zIndex = '1';
|
||||
// Add diagonal stripes with CSS background
|
||||
darkSection.style.backgroundImage = 'repeating-linear-gradient(45deg, rgba(255,255,255,0.3), rgba(255,255,255,0.3) 5px, transparent 5px, transparent 10px)';
|
||||
bar.parentNode.appendChild(darkSection);
|
||||
|
||||
// Add a dashed "tear line" at the transition point
|
||||
const tearLine = document.createElement('div');
|
||||
tearLine.style.position = 'absolute';
|
||||
tearLine.style.left = '85%';
|
||||
// Center the tear line vertically and make it 1.5x as tall as the bar
|
||||
tearLine.style.top = '50%';
|
||||
tearLine.style.transform = 'translateY(-50%)';
|
||||
tearLine.style.height = '54px'; // 1.5x the bar height (36px)
|
||||
tearLine.style.width = '2px';
|
||||
tearLine.style.backgroundColor = 'white';
|
||||
tearLine.style.borderLeft = '2px dashed rgba(0, 0, 0, 0.3)';
|
||||
tearLine.style.zIndex = '2'; // Above the bar
|
||||
bar.parentNode.appendChild(tearLine);
|
||||
}
|
||||
// Function to calculate the appropriate max display cost based on visible/selected entries
|
||||
function calculateDisplayMaxCost() {
|
||||
// Get the appropriate set of rows based on the current mode and selection state
|
||||
let rowsToConsider;
|
||||
|
||||
if (currentMode === 'view' && selectedRows.size > 0) {
|
||||
// In view mode with selections, only consider selected rows
|
||||
rowsToConsider = Array.from(allMainRows).filter(row => {
|
||||
const rowIndex = row.querySelector('.row-selector')?.dataset.rowIndex;
|
||||
return rowIndex && selectedRows.has(rowIndex) && !row.classList.contains('hidden-by-search');
|
||||
});
|
||||
} else {
|
||||
// Set width to 0 if cost is 0 or negative
|
||||
bar.style.width = '0%';
|
||||
// In other modes or without selections, consider all visible rows
|
||||
rowsToConsider = getVisibleMainRows();
|
||||
}
|
||||
});
|
||||
|
||||
// Calculate and add cost ticks dynamically
|
||||
const costCells = document.querySelectorAll('.cost-bar-cell');
|
||||
if (costCells.length > 0) {
|
||||
const MAX_DISPLAY_COST = 50; // $50 limit for visual display
|
||||
|
||||
// Generate fixed tick values at $0, $10, $20, $30, $40, $50
|
||||
const tickValues = [0, 10, 20, 30, 40, 50];
|
||||
|
||||
// Calculate percentage positions for each tick on the linear scale
|
||||
const tickPercentages = tickValues.map(tickCost => {
|
||||
return (tickCost / MAX_DISPLAY_COST) * 100;
|
||||
// Find the maximum cost among the rows to consider
|
||||
let maxCost = 0;
|
||||
rowsToConsider.forEach(row => {
|
||||
const costBar = row.querySelector('.cost-bar');
|
||||
if (costBar) {
|
||||
const cost = parseFloat(costBar.dataset.cost || '0');
|
||||
if (cost > maxCost) maxCost = cost;
|
||||
}
|
||||
});
|
||||
|
||||
// Cap at 50 if any entries exceed that amount, otherwise use actual max
|
||||
return maxCost > 50 ? 50 : Math.max(1, maxCost); // Ensure at least 1 to avoid division by zero
|
||||
}
|
||||
|
||||
// Process cost bars with dynamic scale
|
||||
function updateCostBars() {
|
||||
const costBars = document.querySelectorAll('.cost-bar');
|
||||
const currentMaxDisplayCost = calculateDisplayMaxCost();
|
||||
|
||||
// Remove existing special indicators first
|
||||
document.querySelectorAll('.dark-section, .tear-line').forEach(el => el.remove());
|
||||
|
||||
costBars.forEach(bar => {
|
||||
const cost = parseFloat(bar.dataset.cost);
|
||||
|
||||
if (cost > 0) {
|
||||
// Calculate percentage based on the dynamic display max
|
||||
const percent = Math.min(cost, currentMaxDisplayCost) / currentMaxDisplayCost * 100;
|
||||
// Clamp percentage between 0 and 100
|
||||
bar.style.width = Math.max(0, Math.min(100, percent)) + '%';
|
||||
|
||||
// Mark bars that exceed the limit (only if our display max is capped at 50)
|
||||
if (currentMaxDisplayCost === 50 && cost > 50) {
|
||||
// Create a darker section at the end with diagonal stripes
|
||||
const darkSection = document.createElement('div');
|
||||
darkSection.className = 'bar-viz dark-section';
|
||||
darkSection.style.width = '15%'; // From 85% to 100%
|
||||
darkSection.style.left = '85%';
|
||||
darkSection.style.backgroundColor = 'rgba(13, 110, 253, 0.6)'; // Darker blue
|
||||
darkSection.style.borderRight = '1px solid rgba(13, 110, 253, 0.8)';
|
||||
darkSection.style.zIndex = '1';
|
||||
// Add diagonal stripes with CSS background
|
||||
darkSection.style.backgroundImage = 'repeating-linear-gradient(45deg, rgba(255,255,255,0.3), rgba(255,255,255,0.3) 5px, transparent 5px, transparent 10px)';
|
||||
bar.parentNode.appendChild(darkSection);
|
||||
|
||||
// Add a dashed "tear line" at the transition point
|
||||
const tearLine = document.createElement('div');
|
||||
tearLine.className = 'tear-line';
|
||||
tearLine.style.position = 'absolute';
|
||||
tearLine.style.left = '85%';
|
||||
// Center the tear line vertically and make it 1.5x as tall as the bar
|
||||
tearLine.style.top = '50%';
|
||||
tearLine.style.transform = 'translateY(-50%)';
|
||||
tearLine.style.height = '54px'; // 1.5x the bar height (36px)
|
||||
tearLine.style.width = '2px';
|
||||
tearLine.style.backgroundColor = 'white';
|
||||
tearLine.style.borderLeft = '2px dashed rgba(0, 0, 0, 0.3)';
|
||||
tearLine.style.zIndex = '2'; // Above the bar
|
||||
bar.parentNode.appendChild(tearLine);
|
||||
}
|
||||
} else {
|
||||
// Set width to 0 if cost is 0 or negative
|
||||
bar.style.width = '0%';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Call this initially to set up the bars
|
||||
updateCostBars();
|
||||
|
||||
// Update cost ticks dynamically based on current max display cost
|
||||
function updateCostTicks() {
|
||||
const costCells = document.querySelectorAll('.cost-bar-cell');
|
||||
if (costCells.length === 0) return;
|
||||
|
||||
const currentMaxDisplayCost = calculateDisplayMaxCost();
|
||||
|
||||
// Remove existing ticks first
|
||||
document.querySelectorAll('.cost-tick').forEach(tick => tick.remove());
|
||||
|
||||
// Generate appropriate tick values based on current max
|
||||
let tickValues = [];
|
||||
|
||||
if (currentMaxDisplayCost === 50) {
|
||||
// Fixed ticks at $0, $10, $20, $30, $40, $50 when we're at the cap
|
||||
tickValues = [0, 10, 20, 30, 40, 50];
|
||||
} else {
|
||||
// Dynamic ticks based on actual max
|
||||
const tickCount = 5; // Create 5 segments (6 ticks including 0)
|
||||
for (let i = 0; i <= tickCount; i++) {
|
||||
tickValues.push(Math.round((i / tickCount) * currentMaxDisplayCost * 100) / 100);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate percentage positions for each tick
|
||||
const tickPercentages = tickValues.map(tickCost => {
|
||||
return (tickCost / currentMaxDisplayCost) * 100;
|
||||
});
|
||||
|
||||
// Add tick divs to each cost cell
|
||||
costCells.forEach(cell => {
|
||||
const costBar = cell.querySelector('.cost-bar');
|
||||
// Use optional chaining and provide '0' as fallback if costBar or dataset.cost is missing
|
||||
const cost = parseFloat(costBar?.dataset?.cost || '0');
|
||||
|
||||
|
||||
// Only add ticks if the cost is actually greater than 0
|
||||
if (cost > 0) {
|
||||
tickPercentages.forEach((percent, index) => {
|
||||
|
@ -286,15 +345,15 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
const tick = document.createElement('div');
|
||||
tick.className = 'cost-tick';
|
||||
tick.style.left = `${percent}%`;
|
||||
|
||||
// No dollar amount labels
|
||||
|
||||
cell.appendChild(tick);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Call this initially to set up the ticks
|
||||
updateCostTicks();
|
||||
|
||||
|
||||
// --- New Event Listeners ---
|
||||
|
@ -340,6 +399,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
}
|
||||
// Update select-all checkbox state
|
||||
updateSelectAllCheckboxState();
|
||||
|
||||
// Update cost bars and ticks if in view mode, as selection affects what's shown
|
||||
if (currentMode === 'view') {
|
||||
updateCostBars();
|
||||
updateCostTicks();
|
||||
}
|
||||
}
|
||||
}); // End of tableBody listener
|
||||
|
||||
|
@ -369,6 +434,10 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
});
|
||||
// After bulk change, ensure the selectAll checkbox state is correct (not indeterminate)
|
||||
updateSelectAllCheckboxState();
|
||||
|
||||
// Update cost bars and ticks after selection changes
|
||||
updateCostBars();
|
||||
updateCostTicks();
|
||||
});
|
||||
|
||||
// Listener for search input
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue