fix: set max 6 months for user entered time (#4384)

* fix: set max 6 months for user entered time

* fix: set max 6 months for user entered time
This commit is contained in:
Yunus M 2024-01-17 13:01:55 +05:30 committed by GitHub
parent abaf6126e5
commit 00c9ef50de
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 102 additions and 61 deletions

View File

@ -1,3 +1,8 @@
.custom-time-picker {
display: flex;
flex-direction: column;
}
.time-options-container { .time-options-container {
.time-options-item { .time-options-item {
margin: 2px 0; margin: 2px 0;
@ -43,7 +48,9 @@
.valid-format-error { .valid-format-error {
margin-top: 4px; margin-top: 4px;
color: var(--bg-cherry-400, #ea6d71); color: var(--bg-cherry-400) !important;
font-size: 13px !important;
font-weight: 400 !important;
} }
.lightMode { .lightMode {
@ -80,9 +87,4 @@
color: rgba($color: #000000, $alpha: 0.4); color: rgba($color: #000000, $alpha: 0.4);
} }
} }
.valid-format-error {
margin-top: 4px;
color: var(--bg-cherry-400, #ea6d71);
}
} }

View File

@ -2,7 +2,7 @@
/* eslint-disable jsx-a11y/no-static-element-interactions */ /* eslint-disable jsx-a11y/no-static-element-interactions */
import './CustomTimePicker.styles.scss'; import './CustomTimePicker.styles.scss';
import { Input, Popover, Tooltip } from 'antd'; import { Input, Popover, Tooltip, Typography } from 'antd';
import cx from 'classnames'; import cx from 'classnames';
import { Options } from 'container/TopNav/DateTimeSelection/config'; import { Options } from 'container/TopNav/DateTimeSelection/config';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
@ -11,8 +11,11 @@ import { CheckCircle, ChevronDown, Clock } from 'lucide-react';
import { ChangeEvent, useEffect, useState } from 'react'; import { ChangeEvent, useEffect, useState } from 'react';
import { popupContainer } from 'utils/selectPopupContainer'; import { popupContainer } from 'utils/selectPopupContainer';
const maxAllowedMinTimeInMonths = 6;
interface CustomTimePickerProps { interface CustomTimePickerProps {
onSelect: (value: string) => void; onSelect: (value: string) => void;
onError: (value: boolean) => void;
items: any[]; items: any[];
selectedValue: string; selectedValue: string;
selectedTime: string; selectedTime: string;
@ -21,6 +24,7 @@ interface CustomTimePickerProps {
function CustomTimePicker({ function CustomTimePicker({
onSelect, onSelect,
onError,
items, items,
selectedValue, selectedValue,
selectedTime, selectedTime,
@ -34,6 +38,9 @@ function CustomTimePicker({
const [inputValue, setInputValue] = useState(''); const [inputValue, setInputValue] = useState('');
const [inputStatus, setInputStatus] = useState<'' | 'error' | 'success'>(''); const [inputStatus, setInputStatus] = useState<'' | 'error' | 'success'>('');
const [inputErrorMessage, setInputErrorMessage] = useState<string | null>(
null,
);
const [isInputFocused, setIsInputFocused] = useState(false); const [isInputFocused, setIsInputFocused] = useState(false);
const getSelectedTimeRangeLabel = ( const getSelectedTimeRangeLabel = (
@ -71,6 +78,8 @@ function CustomTimePicker({
const isValidFormat = /^(\d+)([mhdw])$/.test(inputValue); const isValidFormat = /^(\d+)([mhdw])$/.test(inputValue);
if (isValidFormat) { if (isValidFormat) {
setInputStatus('success'); setInputStatus('success');
onError(false);
setInputErrorMessage(null);
const match = inputValue.match(/^(\d+)([mhdw])$/); const match = inputValue.match(/^(\d+)([mhdw])$/);
@ -78,6 +87,10 @@ function CustomTimePicker({
const unit = match[2]; const unit = match[2];
const currentTime = dayjs(); const currentTime = dayjs();
const maxAllowedMinTime = currentTime.subtract(
maxAllowedMinTimeInMonths,
'month',
);
let minTime = null; let minTime = null;
switch (unit) { switch (unit) {
@ -98,9 +111,17 @@ function CustomTimePicker({
break; break;
} }
onValidCustomDateChange([minTime, currentTime]); if (minTime && minTime < maxAllowedMinTime) {
setInputStatus('error');
onError(true);
setInputErrorMessage('Please enter time less than 6 months');
} else {
onValidCustomDateChange([minTime, currentTime]);
}
} else { } else {
setInputStatus('error'); setInputStatus('error');
onError(true);
setInputErrorMessage(null);
} }
}, 300); }, 300);
@ -128,6 +149,8 @@ function CustomTimePicker({
onSelect(value); onSelect(value);
setSelectedTimePlaceholderValue(label); setSelectedTimePlaceholderValue(label);
setInputStatus(''); setInputStatus('');
onError(false);
setInputErrorMessage(null);
setInputValue(''); setInputValue('');
hide(); hide();
}} }}
@ -153,55 +176,64 @@ function CustomTimePicker({
}; };
return ( return (
<Popover <div className="custom-time-picker">
placement="bottomRight" <Popover
getPopupContainer={popupContainer} className="timeSelection-input-container"
content={content} placement="bottomRight"
arrow={false} getPopupContainer={popupContainer}
open={open} content={content}
onOpenChange={handleOpenChange} arrow={false}
trigger={['click']} open={open}
style={{ onOpenChange={handleOpenChange}
padding: 0, trigger={['click']}
}}
>
<Input
className="timeSelection-input"
type="text"
style={{ style={{
minWidth: '120px', padding: 0,
width: '100%',
}} }}
status={inputValue && inputStatus === 'error' ? 'error' : ''} >
allowClear={!isInputFocused && selectedTime === 'custom'} <Input
placeholder={ className="timeSelection-input"
isInputFocused type="text"
? 'Time Format (1m or 2h or 3d or 4w)' style={{
: selectedTimePlaceholderValue minWidth: '120px',
} width: '100%',
value={inputValue} }}
onFocus={handleFocus} status={inputValue && inputStatus === 'error' ? 'error' : ''}
onBlur={handleBlur} allowClear={!isInputFocused && selectedTime === 'custom'}
onChange={handleInputChange} placeholder={
prefix={ isInputFocused
inputValue && inputStatus === 'success' ? ( ? 'Time Format (1m or 2h or 3d or 4w)'
<CheckCircle size={14} color="#51E7A8" /> : selectedTimePlaceholderValue
) : ( }
<Tooltip title="Enter time in format (e.g., 1m, 2h, 2d, 4w)"> value={inputValue}
<Clock size={14} /> onFocus={handleFocus}
</Tooltip> onBlur={handleBlur}
) onChange={handleInputChange}
} prefix={
suffix={ inputValue && inputStatus === 'success' ? (
<ChevronDown <CheckCircle size={14} color="#51E7A8" />
size={14} ) : (
onClick={(): void => { <Tooltip title="Enter time in format (e.g., 1m, 2h, 3d, 4w)">
setOpen(!open); <Clock size={14} />
}} </Tooltip>
/> )
} }
/> suffix={
</Popover> <ChevronDown
size={14}
onClick={(): void => {
setOpen(!open);
}}
/>
}
/>
</Popover>
{inputStatus === 'error' && inputErrorMessage && (
<Typography.Title level={5} className="valid-format-error">
{inputErrorMessage}
</Typography.Title>
)}
</div>
); );
} }

View File

@ -36,6 +36,8 @@ function DateTimeSelection({
}: Props): JSX.Element { }: Props): JSX.Element {
const [formSelector] = Form.useForm(); const [formSelector] = Form.useForm();
const [hasSelectedTimeError, setHasSelectedTimeError] = useState(false);
const urlQuery = useUrlQuery(); const urlQuery = useUrlQuery();
const searchStartTime = urlQuery.get('startTime'); const searchStartTime = urlQuery.get('startTime');
const searchEndTime = urlQuery.get('endTime'); const searchEndTime = urlQuery.get('endTime');
@ -292,6 +294,9 @@ function DateTimeSelection({
onSelect={(value: unknown): void => { onSelect={(value: unknown): void => {
onSelectHandler(value as Time); onSelectHandler(value as Time);
}} }}
onError={(hasError: boolean): void => {
setHasSelectedTimeError(hasError);
}}
selectedTime={selectedTime} selectedTime={selectedTime}
onValidCustomDateChange={(dateTime): void => onValidCustomDateChange={(dateTime): void =>
onCustomDateHandler(dateTime as DateTimeRangeType) onCustomDateHandler(dateTime as DateTimeRangeType)
@ -319,12 +324,14 @@ function DateTimeSelection({
</FormContainer> </FormContainer>
</Form> </Form>
<RefreshText {!hasSelectedTimeError && (
{...{ <RefreshText
onLastRefreshHandler, {...{
}} onLastRefreshHandler,
refreshButtonHidden={refreshButtonHidden} }}
/> refreshButtonHidden={refreshButtonHidden}
/>
)}
<CustomDateTimeModal <CustomDateTimeModal
visible={customDateTimeVisible} visible={customDateTimeVisible}