[WEB-4677] improvement: add defaultOpen property to CustomSearchSelect (#7576)

* [WEB-4677] improvement: add defaultOpen property to CustomSearchSelect

* improvement: add utils to format time duration

* improvement: added initializing state for project store

* improvement: minor changes in automations page
This commit is contained in:
Prateek Shourya 2025-08-12 19:37:53 +05:30 committed by GitHub
parent 5629a4d4b6
commit 34c6047d80
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 74 additions and 7 deletions

View file

@ -6,9 +6,9 @@ import { usePopper } from "react-popper";
// plane imports
import { useOutsideClickDetector } from "@plane/hooks";
// local imports
import { cn } from "../utils";
import { useDropdownKeyDown } from "../hooks/use-dropdown-key-down";
import { Tooltip } from "../tooltip";
import { cn } from "../utils";
import { ICustomSearchSelectProps } from "./helper";
export const CustomSearchSelect = (props: ICustomSearchSelectProps) => {
@ -34,12 +34,13 @@ export const CustomSearchSelect = (props: ICustomSearchSelectProps) => {
value,
tabIndex,
noResultsMessage = "No matches found",
defaultOpen = false,
} = props;
const [query, setQuery] = useState("");
const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | null>(null);
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
const [isOpen, setIsOpen] = useState(false);
const [isOpen, setIsOpen] = useState(defaultOpen);
// refs
const dropdownRef = useRef<HTMLDivElement | null>(null);

View file

@ -19,6 +19,7 @@ export interface IDropdownProps {
placement?: Placement;
tabIndex?: number;
useCaptureForOutsideClick?: boolean;
defaultOpen?: boolean;
}
export interface IPortalProps {

View file

@ -24,7 +24,7 @@ export const renderFormattedDate = (
try {
// Format the date in the format provided or default format (MMM dd, yyyy)
formattedDate = format(parsedDate, formatToken);
} catch (e) {
} catch (_e) {
// Format the date in format (MMM dd, yyyy) in case of any error
formattedDate = format(parsedDate, "MMM dd, yyyy");
}
@ -287,7 +287,7 @@ export const getDate = (date: string | Date | undefined | null): Date | undefine
if (!isNumber(year) || !isNumber(month) || !isNumber(day)) return;
return new Date(year, month - 1, day);
} catch (e) {
} catch (_e) {
return undefined;
}
};
@ -531,3 +531,44 @@ export const formatDateRange = (
return "";
};
// Duration Helpers
/**
* @returns {string} formatted duration in human readable format
* @description Converts seconds to human readable duration format (e.g., "1 hr 20 min 5 sec")
* @param {number} seconds - The duration in seconds
* @example formatDuration(3665) // "1 hr 1 min 5 sec"
* @example formatDuration(125) // "2 min 5 sec"
* @example formatDuration(45) // "45 sec"
*/
export const formatDuration = (seconds: number | undefined | null): string => {
// Return "N/A" if seconds is not a valid number
if (!isNumber(seconds) || seconds === null || seconds === undefined || seconds < 0) {
return "N/A";
}
// Round to nearest second
const totalSeconds = Math.round(seconds);
// Calculate hours, minutes, and seconds
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const remainingSeconds = totalSeconds % 60;
// Build the formatted string
const parts: string[] = [];
if (hours > 0) {
parts.push(`${hours} hr${hours !== 1 ? "" : ""}`); // Always use "hr" for consistency
}
if (minutes > 0) {
parts.push(`${minutes} min`);
}
if (remainingSeconds > 0 || parts.length === 0) {
parts.push(`${remainingSeconds} sec`);
}
return parts.join(" ");
};