Skip to main content
Glama

@arizeai/phoenix-mcp

Official
by Arize-ai
TimeRangeSelector.tsx5.06 kB
import { PropsWithChildren } from "react"; import { Dialog, DialogTrigger } from "react-aria-components"; import { css } from "@emotion/react"; import { Button, Flex, Heading, Icon, Icons, ListBox, ListBoxItem, Popover, PopoverArrow, SelectChevronUpDownIcon, TimeRangeForm, View, } from "@phoenix/components"; import { ComponentSize } from "@phoenix/components/types"; import { timeRangeFormatter } from "@phoenix/utils/timeFormatUtils"; import { LAST_N_TIME_RANGES } from "./constants"; import { OpenTimeRangeWithKey } from "./types"; import { getTimeRangeFromLastNTimeRangeKey, isTimeRangeKey } from "./utils"; export type TimeRangeSelectorProps = { isDisabled?: boolean; value: OpenTimeRangeWithKey; onChange: (timeRange: OpenTimeRangeWithKey) => void; size?: ComponentSize; }; const listBoxCSS = css` width: 130px; `; /** * Get the display text for the time range key. Shows the explicit time range in the case of "custom" */ function getDisplayText({ timeRangeKey, start, end }: OpenTimeRangeWithKey) { if (timeRangeKey === "custom") { return timeRangeFormatter({ start, end }); } const rangeValue = LAST_N_TIME_RANGES.find( (range) => range.key === timeRangeKey ); if (!rangeValue) { // Should never happen but must make sure to handle it return "invalid"; } return rangeValue.label; } export function TimeRangeSelector(props: TimeRangeSelectorProps) { const { value, isDisabled, onChange, size = "S" } = props; const { timeRangeKey, start, end } = value; return ( <DialogTrigger> <Button size={size} leadingVisual={<Icon svg={<Icons.CalendarOutline />} />} isDisabled={isDisabled} > {getDisplayText(value)} <SelectChevronUpDownIcon /> </Button> <Popover placement="bottom end"> <Dialog> {({ close }) => ( <> <PopoverArrow /> <Flex direction="row"> <CustomTimeRangeWrap visible={timeRangeKey === "custom"}> {/* We force re-mount to reset the dirty state in the form */} {timeRangeKey === "custom" && ( <Flex direction="column" gap="size-100" height="100%"> <Heading level={2} weight="heavy"> Time Range </Heading> <TimeRangeForm initialValue={{ start, end }} onSubmit={(timeRange) => { onChange && onChange({ timeRangeKey: "custom", ...timeRange, }); close(); }} /> </Flex> )} </CustomTimeRangeWrap> <ListBox aria-label="time range preset selection" selectionMode="single" autoFocus selectedKeys={[timeRangeKey]} css={listBoxCSS} onSelectionChange={(selection) => { if (selection === "all") { close(); return; } const timeRangeKey = selection.keys().next().value; if (!isTimeRangeKey(timeRangeKey)) { // Sometimes the time range is undefined for some reason // TODO: figure out why this happens return; } if (timeRangeKey !== "custom") { // Compute the time range onChange({ timeRangeKey, ...getTimeRangeFromLastNTimeRangeKey(timeRangeKey), }); close(); return; } else { onChange({ timeRangeKey, start: start, end: end, }); } }} > {LAST_N_TIME_RANGES.map(({ key, label }) => ( <ListBoxItem key={key} id={key}> {label} </ListBoxItem> ))} <ListBoxItem key="custom" id="custom"> Custom </ListBoxItem> </ListBox> </Flex> </> )} </Dialog> </Popover> </DialogTrigger> ); } function CustomTimeRangeWrap({ children, visible, }: PropsWithChildren<{ visible: boolean }>) { return ( <div css={css` display: ${visible ? "block" : "none"}; `} > <View borderEndWidth="thin" borderColor="light" padding="size-200" height="100%" > {children} </View> </div> ); }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Arize-ai/phoenix'

If you have feedback or need assistance with the MCP directory API, please join our Discord server