diff --git a/src/components/RecentActivity/LiveView/ChangeStatus/index.tsx b/src/components/RecentActivity/LiveView/ChangeStatus/index.tsx index a45bd46dc..30d0ae38d 100644 --- a/src/components/RecentActivity/LiveView/ChangeStatus/index.tsx +++ b/src/components/RecentActivity/LiveView/ChangeStatus/index.tsx @@ -5,9 +5,6 @@ import { LiveDataDurationPercentile } from "../types"; import * as s from "./styles"; import { ChangeStatusProps } from "./types"; -const DURATION_RATIO_MIN_LIMIT = 0.1; -const DURATION_DIFF_MIN_LIMIT = 10 * 1000; // in nanoseconds - const getStatusString = (percentile: LiveDataDurationPercentile) => { if (!percentile.previousDuration) { return ""; @@ -74,39 +71,12 @@ const renderArrowIcon = ( export const ChangeStatus = (props: ChangeStatusProps) => { const theme = useTheme(); - if (props.percentiles.length === 0) { - return null; - } - - const percentile = props.percentiles.find( - (x) => x.previousDuration && typeof x.changeVerified === "boolean" - ); - - if (!percentile) { - return null; - } - - let changeMeaningfulEnough = false; - - if (percentile.previousDuration) { - const diff = Math.abs( - percentile.currentDuration.raw - percentile.previousDuration.raw - ); - - changeMeaningfulEnough = - diff / percentile.previousDuration.raw > DURATION_RATIO_MIN_LIMIT && - diff > DURATION_DIFF_MIN_LIMIT; - } - - if (!changeMeaningfulEnough) { - return null; - } return ( - {renderArrowIcon(percentile, theme)} - {getStatusString(percentile)} - {!percentile.changeVerified && ( + {renderArrowIcon(props.percentile, theme)} + {getStatusString(props.percentile)} + {!props.percentile.changeVerified && ( Evaluating )} diff --git a/src/components/RecentActivity/LiveView/ChangeStatus/types.ts b/src/components/RecentActivity/LiveView/ChangeStatus/types.ts index e7cd021fc..33774d49b 100644 --- a/src/components/RecentActivity/LiveView/ChangeStatus/types.ts +++ b/src/components/RecentActivity/LiveView/ChangeStatus/types.ts @@ -1,5 +1,5 @@ import { LiveDataDurationPercentile } from "../types"; export interface ChangeStatusProps { - percentiles: LiveDataDurationPercentile[]; + percentile: LiveDataDurationPercentile; } diff --git a/src/components/RecentActivity/LiveView/index.tsx b/src/components/RecentActivity/LiveView/index.tsx index 72534b96c..18356c09e 100644 --- a/src/components/RecentActivity/LiveView/index.tsx +++ b/src/components/RecentActivity/LiveView/index.tsx @@ -1,5 +1,5 @@ import { format } from "date-fns"; -import { UIEvent, useEffect, useRef, useState } from "react"; +import { UIEvent, useEffect, useMemo, useRef, useState } from "react"; import useDimensions from "react-cool-dimensions"; import useScrollbarSize from "react-scrollbar-size"; @@ -40,6 +40,8 @@ import { } from "./types"; const ZOOM_FACTOR = 1.2; +const DURATION_RATIO_MIN_LIMIT = 0.1; +const DURATION_DIFF_MIN_LIMIT = 10 * 1000; // in nanoseconds const PERCENTILES = [ { label: "Median", percentile: 0.5 }, @@ -328,8 +330,40 @@ export const LiveView = (props: LiveViewProps) => { ? scrollbar.width : 0; + const changedPercentile = useMemo(() => { + if (props.data.durationData.percentiles.length === 0) { + return null; + } + + const percentile = props.data.durationData.percentiles.find( + (x) => x.previousDuration && typeof x.changeVerified === "boolean" + ); + + if (!percentile) { + return null; + } + + let changeMeaningfulEnough = false; + + if (percentile.previousDuration) { + const diff = Math.abs( + percentile.currentDuration.raw - percentile.previousDuration.raw + ); + + changeMeaningfulEnough = + diff / percentile.previousDuration.raw > DURATION_RATIO_MIN_LIMIT && + diff > DURATION_DIFF_MIN_LIMIT; + } + + if (!changeMeaningfulEnough) { + return null; + } + + return percentile; + }, [props.data.durationData.percentiles]); + return ( - + @@ -355,10 +389,14 @@ export const LiveView = (props: LiveViewProps) => { - - - - + {changedPercentile && ( + + + + )} + + [ + HEADER_HEIGHT, + ZOOM_BUTTONS_CONTAINER_HEIGHT, + isChangeStatusBarPresent ? CHANGE_STATUS_CONTAINER_HEIGHT : 0, + FOOTER_HEIGHT + ] + .filter((x) => x > 0) + .reduce((acc, cur) => acc + cur + CONTAINER_GAP, 0) + CONTAINER_GAP; + +export const Container = styled.div<{ isChangeStatusBarPresent: boolean }>` display: flex; flex-direction: column; height: 100%; - gap: 12px; + gap: ${CONTAINER_GAP}px; + min-height: ${({ isChangeStatusBarPresent }) => + getContainerMinHeight(isChangeStatusBarPresent)}px; border: 1px solid ${({ theme }) => { @@ -37,6 +56,9 @@ export const Header = styled.div` font-weight: 500; font-size: 10px; line-height: 12px; + height: ${HEADER_HEIGHT}px; + box-sizing: border-box; + flex: none; border-bottom: ${({ theme }) => { switch (theme.mode) { @@ -114,9 +136,15 @@ export const CloseButton = styled.button` cursor: pointer; `; -export const ChartsContainer = styled.div` +export const ChartsContainer = styled.div<{ + isChangeStatusBarPresent: boolean; +}>` display: flex; - height: calc(100% - 174px); + height: calc( + 100% - + ${({ isChangeStatusBarPresent }) => + getContainerMinHeight(isChangeStatusBarPresent)}px + ); padding-right: 12px; `; @@ -125,6 +153,8 @@ export const ZoomButtonsContainer = styled.div` justify-content: flex-end; gap: 4px; padding: 0 12px; + height: ${ZOOM_BUTTONS_CONTAINER_HEIGHT}px; + flex: none; `; export const ZoomButton = styled.button` @@ -168,7 +198,8 @@ export const ZoomButton = styled.button` export const ChangeStatusContainer = styled.div` padding: 0 12px; - height: 32px; + height: ${CHANGE_STATUS_CONTAINER_HEIGHT}px; + flex: none; `; export const AxisChartContainer = styled.div` @@ -189,6 +220,9 @@ export const Footer = styled.div` flex-direction: column; gap: 4px; padding: 4px 12px; + height: ${FOOTER_HEIGHT}px; + box-sizing: border-box; + flex: none; `; export const LegendContainer = styled.div`