ydb-embedded-ui 4.31.0 → 4.31.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -15,6 +15,8 @@ docker pull cr.yandex/yc/yandex-docker-local-ydb
15
15
  docker run -dp 8765:8765 cr.yandex/yc/yandex-docker-local-ydb
16
16
  ```
17
17
 
18
+ Open http://localhost:8765 to view it in the browser.
19
+
18
20
  ## Development
19
21
 
20
22
  1. Run on a machine with Docker installed:
@@ -8,12 +8,13 @@ export const convertResponse = (
8
8
  const preparedMetrics = data
9
9
  .map(({datapoints, target}) => {
10
10
  const metricDescription = metrics.find((metric) => metric.target === target);
11
- const chartData = datapoints.map((datapoint) => datapoint[0] || 0);
12
11
 
13
12
  if (!metricDescription) {
14
13
  return undefined;
15
14
  }
16
15
 
16
+ const chartData = datapoints.map((datapoint) => datapoint[0]);
17
+
17
18
  return {
18
19
  ...metricDescription,
19
20
  data: chartData,
@@ -1,4 +1,5 @@
1
1
  import {formatBytes} from '../../utils/bytesParsers';
2
+ import {EMPTY_DATA_PLACEHOLDER} from '../../utils/constants';
2
3
  import {roundToPrecision} from '../../utils/dataFormatters/dataFormatters';
3
4
  import {formatToMs} from '../../utils/timeParsers';
4
5
  import {isNumeric} from '../../utils/utils';
@@ -18,11 +19,19 @@ export const getDefaultDataFormatter = (dataType?: ChartDataType) => {
18
19
  }
19
20
  };
20
21
 
22
+ // Values in y axis won't be null and will always be present and properly formatted
23
+ // EMPTY_DATA_PLACEHOLDER is actually empty data format for values in a tooltip
21
24
  function formatChartValueToMs(value: ChartValue) {
25
+ if (value === null) {
26
+ return EMPTY_DATA_PLACEHOLDER;
27
+ }
22
28
  return formatToMs(roundToPrecision(convertToNumber(value), 2));
23
29
  }
24
30
 
25
31
  function formatChartValueToSize(value: ChartValue) {
32
+ if (value === null) {
33
+ return EMPTY_DATA_PLACEHOLDER;
34
+ }
26
35
  return formatBytes({value: convertToNumber(value), precision: 3});
27
36
  }
28
37
 
@@ -15,7 +15,7 @@ export interface MetricDescription {
15
15
  }
16
16
 
17
17
  export interface PreparedMetric extends MetricDescription {
18
- data: number[];
18
+ data: (number | null)[];
19
19
  }
20
20
 
21
21
  export interface PreparedMetricsData {
@@ -76,7 +76,7 @@ export const VirtualTable = <T,>({
76
76
 
77
77
  const [error, setError] = useState<IResponseError>();
78
78
 
79
- const [pendingRequests, setPendingRequests] = useState<Record<string, NodeJS.Timeout>>({});
79
+ const pendingRequests = useRef<Record<string, ReturnType<typeof setTimeout>>>({});
80
80
 
81
81
  const fetchChunkData = useCallback(
82
82
  async (id: string) => {
@@ -105,10 +105,13 @@ export const VirtualTable = <T,>({
105
105
  }
106
106
  }, DEFAULT_REQUEST_TIMEOUT);
107
107
 
108
- setPendingRequests((reqs) => {
109
- reqs[id] = timer;
110
- return reqs;
111
- });
108
+ // Chunk data load could be triggered by different events
109
+ // Cancel previous chunk request, while it is pending (instead of concurrentId)
110
+ if (pendingRequests.current[id]) {
111
+ const oldTimer = pendingRequests.current[id];
112
+ window.clearTimeout(oldTimer);
113
+ }
114
+ pendingRequests.current[id] = timer;
112
115
  },
113
116
  [fetchData, limit, sortParams],
114
117
  );
@@ -117,20 +120,27 @@ export const VirtualTable = <T,>({
117
120
  dispatch(initChunk(id));
118
121
  }, []);
119
122
 
120
- const onLeave = useCallback<OnLeave>(
121
- (id) => {
122
- dispatch(removeChunk(id));
123
+ const onLeave = useCallback<OnLeave>((id) => {
124
+ dispatch(removeChunk(id));
125
+
126
+ // If there is a pending request for the removed chunk, cancel it
127
+ // It made to prevent excessive requests on fast scroll
128
+ if (pendingRequests.current[id]) {
129
+ const timer = pendingRequests.current[id];
130
+ window.clearTimeout(timer);
131
+ delete pendingRequests.current[id];
132
+ }
133
+ }, []);
123
134
 
124
- // If there is a pending request for the removed chunk, cancel it
125
- // It made to prevent excessive requests on fast scroll
126
- if (pendingRequests[id]) {
127
- const timer = pendingRequests[id];
135
+ // Cancel all pending requests on component unmount
136
+ useEffect(() => {
137
+ return () => {
138
+ Object.values(pendingRequests.current).forEach((timer) => {
128
139
  window.clearTimeout(timer);
129
- delete pendingRequests[id];
130
- }
131
- },
132
- [pendingRequests],
133
- );
140
+ });
141
+ pendingRequests.current = {};
142
+ };
143
+ }, []);
134
144
 
135
145
  // Load chunks if they become active
136
146
  // This mecanism helps to set chunk active state from different sources, but load data only once
@@ -71,6 +71,8 @@ export const COLORS_PRIORITY = {
71
71
 
72
72
  export const TENANT_OVERVIEW_TABLES_LIMIT = 5;
73
73
 
74
+ export const EMPTY_DATA_PLACEHOLDER = '—';
75
+
74
76
  // ==== Titles ====
75
77
  export const DEVELOPER_UI_TITLE = 'Developer UI';
76
78
  export const CLUSTER_DEFAULT_TITLE = 'Cluster';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "4.31.0",
3
+ "version": "4.31.2",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
@@ -53,9 +53,9 @@
53
53
  "scripts": {
54
54
  "start": "react-app-rewired start",
55
55
  "dev": "DISABLE_ESLINT_PLUGIN=true TSC_COMPILE_ON_ERROR=true REACT_APP_BACKEND=http://localhost:8765 npm start",
56
- "build": "DISABLE_ESLINT_PLUGIN=true react-app-rewired build",
56
+ "build": "rm -rf build && DISABLE_ESLINT_PLUGIN=true react-app-rewired build",
57
57
  "//build:embedded": "echo 'PUBLIC_URL is a setting for create-react-app. Embedded version is built and hosted as is on ydb servers, with no way of knowing the final URL pattern. PUBLIC_URL=. keeps paths to all static relative, allowing servers to handle them as needed'",
58
- "build:embedded": "rm -rf build && PUBLIC_URL=. REACT_APP_BACKEND=http://localhost:8765 npm run build",
58
+ "build:embedded": "GENERATE_SOURCEMAP=false PUBLIC_URL=. REACT_APP_BACKEND=http://localhost:8765 npm run build",
59
59
  "lint:styles": "stylelint 'src/**/*.scss'",
60
60
  "unimported": "npx unimported --no-cache",
61
61
  "package": "rm -rf dist && copyfiles -u 1 'src/**/*' dist",