Add advanced date picker to all the tabs on the usage page (#13221)

* advancedatepicker for tag usage and team usage

* reduce white space in date picker

* selected time range option is visible

* dont wait for apply button to select relative time options
This commit is contained in:
tanjiro
2025-08-02 07:54:49 -07:00
committed by GitHub
parent 44900e781a
commit eb173f9155
2 changed files with 81 additions and 15 deletions
@@ -21,7 +21,7 @@ import {
TabPanels,
Subtitle,
} from "@tremor/react";
import UsageDatePicker from "./shared/usage_date_picker";
import AdvancedDatePicker from "./shared/advanced_date_picker";
import { Select } from 'antd';
import { ActivityMetrics, processActivityData } from './activity_metrics';
import { DailyData, BreakdownMetrics, KeyMetricWithMetadata, EntityMetricWithMetadata } from './usage/types';
@@ -328,7 +328,7 @@ const EntityUsage: React.FC<EntityUsageProps> = ({
<div style={{ width: "100%" }}>
<Grid numItems={2} className="gap-2 w-full mb-4">
<Col>
<UsageDatePicker value={dateValue} onValueChange={setDateValue} />
<AdvancedDatePicker value={dateValue} onValueChange={setDateValue} />
</Col>
{entityList && entityList.length > 0 && (
<Col>
@@ -71,6 +71,7 @@ const AdvancedDatePicker: React.FC<AdvancedDatePickerProps> = ({
}) => {
const [isOpen, setIsOpen] = useState(false)
const [tempValue, setTempValue] = useState<DateRangePickerValue>(value)
const [selectedOption, setSelectedOption] = useState<string | null>(null)
// Custom date inputs only - removed time inputs
const [startDate, setStartDate] = useState("")
@@ -78,6 +79,31 @@ const AdvancedDatePicker: React.FC<AdvancedDatePickerProps> = ({
const dropdownRef = useRef<HTMLDivElement>(null)
// Function to check if current value matches a relative time option
const getMatchingOption = useCallback((currentValue: DateRangePickerValue): string | null => {
if (!currentValue.from || !currentValue.to) return null
for (const option of relativeTimeOptions) {
const optionRange = option.getValue()
// Compare dates with some tolerance (to account for time differences)
const fromMatches = moment(currentValue.from).isSame(moment(optionRange.from), "day")
const toMatches = moment(currentValue.to).isSame(moment(optionRange.to), "day")
if (fromMatches && toMatches) {
return option.shortLabel
}
}
return null
}, [])
// Update selected option when value changes
useEffect(() => {
const matchingOption = getMatchingOption(value)
setSelectedOption(matchingOption)
}, [value, getMatchingOption])
// Validation logic - simplified for dates only
const validateDateRange = useCallback(() => {
if (!startDate || !endDate) {
@@ -171,11 +197,29 @@ const AdvancedDatePicker: React.FC<AdvancedDatePickerProps> = ({
const handleRelativeTimeSelect = (option: RelativeTimeOption) => {
const { from, to } = option.getValue()
const newValue = { from, to }
// Immediately apply the selected option
onValueChange(newValue)
// Apply the same background adjustment logic as the original component
requestIdleCallback(
() => {
const adjustedValue = adjustDateRange(newValue)
onValueChange(adjustedValue)
},
{ timeout: 100 },
)
// Update local state to reflect the selection
setTempValue(newValue)
setSelectedOption(option.shortLabel)
// Update the form inputs to reflect the selection
setStartDate(moment(from).format("YYYY-MM-DD"))
setEndDate(moment(to).format("YYYY-MM-DD"))
// Close the dropdown
setIsOpen(false)
}
const updateTempValueFromInputs = useCallback(() => {
@@ -186,13 +230,18 @@ const AdvancedDatePicker: React.FC<AdvancedDatePickerProps> = ({
const to = moment(endDate, "YYYY-MM-DD").endOf("day")
if (from.isValid() && to.isValid()) {
setTempValue({ from: from.toDate(), to: to.toDate() })
const newValue = { from: from.toDate(), to: to.toDate() }
setTempValue(newValue)
// Check if this matches any preset option
const matchingOption = getMatchingOption(newValue)
setSelectedOption(matchingOption)
}
}
} catch (error) {
console.warn("Invalid date format:", error)
}
}, [startDate, endDate, validation.isValid])
}, [startDate, endDate, validation.isValid, getMatchingOption])
// Update tempValue when inputs change
useEffect(() => {
@@ -229,6 +278,10 @@ const AdvancedDatePicker: React.FC<AdvancedDatePickerProps> = ({
setEndDate(moment(value.to).format("YYYY-MM-DD"))
}
// Reset selected option
const matchingOption = getMatchingOption(value)
setSelectedOption(matchingOption)
setIsOpen(false)
}
@@ -267,17 +320,30 @@ const AdvancedDatePicker: React.FC<AdvancedDatePickerProps> = ({
<div className="p-3 border-b border-gray-200">
<span className="text-sm font-semibold text-gray-900">Relative time (today, 7d, 30d, MTD, YTD)</span>
</div>
<div className="h-[500px] overflow-y-auto">
{relativeTimeOptions.map((option) => (
<div
key={option.label}
className="flex items-center justify-between px-5 py-4 hover:bg-gray-50 cursor-pointer border-b border-gray-100"
onClick={() => handleRelativeTimeSelect(option)}
>
<span className="text-sm text-gray-700">{option.label}</span>
<span className="text-xs text-gray-500 bg-gray-100 px-2 py-1 rounded">{option.shortLabel}</span>
</div>
))}
<div className="h-[350px] overflow-y-auto">
{relativeTimeOptions.map((option) => {
const isSelected = selectedOption === option.shortLabel
return (
<div
key={option.label}
className={`flex items-center justify-between px-5 py-4 cursor-pointer border-b border-gray-100 transition-colors ${
isSelected ? "bg-blue-50 hover:bg-blue-100 border-blue-200" : "hover:bg-gray-50"
}`}
onClick={() => handleRelativeTimeSelect(option)}
>
<span className={`text-sm ${isSelected ? "text-blue-700 font-medium" : "text-gray-700"}`}>
{option.label}
</span>
<span
className={`text-xs px-2 py-1 rounded ${
isSelected ? "text-blue-700 bg-blue-100" : "text-gray-500 bg-gray-100"
}`}
>
{option.shortLabel}
</span>
</div>
)
})}
</div>
</div>