Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix broken target visualisation #422

Merged
merged 2 commits into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .creevey/images/MetricList/Default/chrome.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .creevey/images/MetricList/With Remove all NODATA/chrome.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified .creevey/images/MetricList/With Status Indicator/chrome.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
74 changes: 56 additions & 18 deletions src/Components/MetricList/MetricList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,20 @@ import ArrowBoldDownIcon from "@skbkontur/react-icons/ArrowBoldDown";
import ArrowBoldUpIcon from "@skbkontur/react-icons/ArrowBoldUp";
import TrashIcon from "@skbkontur/react-icons/Trash";
import { Button } from "@skbkontur/react-ui/components/Button";
import { MetricItemList } from "../../Domain/Metric";
import { Metric, MetricItemList } from "../../Domain/Metric";
import cn from "./MetricList.less";
import { FixedSizeList as List } from "react-window";
import type { VariableSizeList } from "react-window";
import { VariableSizeList as List } from "react-window";
import { MetricListItem } from "../MetricListItem/MetricListItem";
import { useEffect, useRef } from "react";

export type SortingColumn = "state" | "name" | "event" | "value";

const MAX_LIST_LENGTH_BEFORE_SCROLLABLE = 25;
const METRIC_LIST_HEIGHT = 500;
const METRIC_LIST_ROW_HEIGHT = 20;
const METRIC_LIST_ROW_PADDING = 5;

type Props = {
status?: boolean;
items: MetricItemList;
Expand All @@ -22,6 +29,21 @@ type Props = {
onNoDataRemove?: () => void;
};

const getItemSize = (_metricName: string, metricData: Metric) => {
const { values } = metricData;
if (!values) {
return METRIC_LIST_ROW_HEIGHT;
}

return Object.keys(values).length * METRIC_LIST_ROW_HEIGHT;
};

const getTotalSize = (entries: [string, Metric][]) =>
entries.reduce(
(totalSize, metric) => (totalSize += getItemSize(...metric)),
METRIC_LIST_ROW_PADDING
);

export default function MetricList(props: Props): React.ReactElement {
const {
status,
Expand All @@ -36,16 +58,22 @@ export default function MetricList(props: Props): React.ReactElement {
} = props;

const sortingIcon = sortingDown ? <ArrowBoldDownIcon /> : <ArrowBoldUpIcon />;

const ref = useRef<VariableSizeList>(null);
const entries = Object.entries(items);

// When the sorting state is changed, call resetAfterIndex to recache row offsets and measurements
useEffect(() => ref.current?.resetAfterIndex(0), [sortingColumn, sortingDown]);

return (
<section className={cn("table")}>
<header
className={cn("row", "header")}
// Если кол-во элементов в списке больше 25, они выходят за границу видимой области, и появляется скроллбар.
// В этом случае добавляем пространство справа, чтобы заголовки не смещались относительно строк в списке.
style={{ scrollbarGutter: entries.length > 25 ? "stable" : "auto" }}
// When the metrics list is over MAX_LIST_LENGTH_BEFORE_SCROLLABLE items, it becomes scrollable.
// Add a scrollbar gutter on the right to align header cells with row cells.
style={{
scrollbarGutter:
entries.length > MAX_LIST_LENGTH_BEFORE_SCROLLABLE ? "stable" : "auto",
}}
>
{status && <div className={cn("state")} />}
<div className={cn("name")}>
Expand Down Expand Up @@ -102,22 +130,32 @@ export default function MetricList(props: Props): React.ReactElement {
</header>
<div className={cn("items")}>
<List
height={500}
ref={ref}
height={
// When the metrics list is over MAX_LIST_LENGTH_BEFORE_SCROLLABLE items, it will have a fixed 500px height.
// Otherwise, the total height will be the sum of individual row heights.
entries.length > MAX_LIST_LENGTH_BEFORE_SCROLLABLE
? METRIC_LIST_HEIGHT
: getTotalSize(entries)
}
width="100%"
itemSize={20}
itemSize={(index) => getItemSize(...entries[index])}
itemCount={entries.length}
itemData={entries}
>
{({ data, index, style }) => (
<MetricListItem
status={status}
data={data}
index={index}
style={style}
onChange={onChange}
onRemove={onRemove}
/>
)}
{({ data, index, style }) => {
const [metricName, metricData] = data[index];
return (
<MetricListItem
status={status ?? false}
metricName={metricName}
metricData={metricData}
style={style}
onChange={onChange}
onRemove={onRemove}
/>
);
}}
</List>
</div>
</section>
Expand Down
9 changes: 4 additions & 5 deletions src/Components/MetricListItem/MetricListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,21 @@ const hideTargetsNames = ({ values }: Metric) => !values || Object.keys(values).

type MetricListItemProps = {
status: boolean;
data: [string, Metric][];
index: number;
metricName: string;
metricData: Metric;
style: React.CSSProperties;
onChange: (metric: string, maintenance: number) => void;
onRemove: (metric: string) => void;
};

export function MetricListItem({
status,
data,
index,
metricName,
metricData,
style,
onChange,
onRemove,
}: MetricListItemProps) {
const [metricName, metricData] = data[index];
const {
value,
values,
Expand Down
15 changes: 12 additions & 3 deletions src/Components/Mobile/MobileMetricsList/MobileMetricsList.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as React from "react";
import { MetricItemList } from "../../../Domain/Metric";
import { Metric, MetricItemList } from "../../../Domain/Metric";
import MobileMetricsListItem from "../MobileMetricsListItem/MobileMetricsListItem";
import cn from "./MobileMetricsList.less";
import { FixedSizeList as List } from "react-window";
import { VariableSizeList as List } from "react-window";
import AutoSizer from "react-virtualized-auto-sizer";

type Props = {
Expand All @@ -12,6 +12,15 @@ type Props = {
withTargets?: boolean;
};

const getItemSize = (_metricName: string, metricData: Metric) => {
const { values } = metricData;
if (!values) {
return 45;
}

return 20 + Object.keys(values).length * 25;
};

export default function MobileMetricsList(props: Props): React.ReactElement {
const { onSetMaintenance, onRemove, metrics, withTargets } = props;
const entries = Object.entries(metrics);
Expand All @@ -23,7 +32,7 @@ export default function MobileMetricsList(props: Props): React.ReactElement {
<List
height={height || 0}
width="100%"
itemSize={53}
itemSize={(index) => getItemSize(...entries[index])}
itemCount={entries.length}
itemData={entries}
>
Expand Down
4 changes: 4 additions & 0 deletions src/Stories/MetricList.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ const items: MetricItemList = {
setup_user: null,
setup_time: null,
},
values: {
T1: 10938918,
T2: 42069,
},
},
"vm-ditrace3.nginx": {
event_timestamp: 1503484033,
Expand Down
Loading