Skip to content

Commit 1ba74bd

Browse files
committed
Merge pull request 'release-1.7.0' (#37) from release-1.7.0 into master
Reviewed-on: https://git.tech.wbsrv.ru/web-server/angie-console-light/pulls/37
2 parents e2a2035 + 2f32619 commit 1ba74bd

File tree

35 files changed

+535
-520
lines changed

35 files changed

+535
-520
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Changelog
22

3+
## [v1.7.0](https://github.com/webserver-llc/angie-console-light/releases/tag/1.7.0) (2025-03-24)
4+
5+
### Added
6+
- Display exact data volumes in bytes on mouse hover
7+
- New "busy" state for upstream peers in the statistics API, indicating that a peer has reached the limit configured by the "max_conns" option.
8+
9+
### Fixed
10+
- Fixed documentation links
11+
312
## [v1.6.1](https://github.com/webserver-llc/angie-console-light/releases/tag/1.6.1) (2025-01-27)
413

514
### Fixed

locales/en/pages/index/aboutangie.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,7 @@
22
"Reload": "Reload",
33
"Config Files": "Configuration",
44
"Address": "Address",
5-
"Last reload": "Last reload"
5+
"Last reload": "Last reload",
6+
"Version": "Version",
7+
"Docs URL": "https://en.angie.software/angie/docs/"
68
}

locales/en/upstreams/peer-tooltip.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"Checking": "Checking",
66
"Up": "Up",
77
"Down": "Down",
8+
"Busy": "Busy",
89
"Type: backup": "Type: backup",
910
"Total downtime:": "Total downtime:",
1011
"Down since:": "Down since:"

locales/ru/pages/index/aboutangie.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,7 @@
22
"Reload": "Перезагрузок",
33
"Config Files": "Конфигурация",
44
"Address": "Адрес",
5-
"Last reload": "Последняя перезагрузка"
5+
"Last reload": "Последняя перезагрузка",
6+
"Version": "Версия",
7+
"Docs URL": "https://angie.software/angie/docs/"
68
}

locales/ru/upstreams/peer-tooltip.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"Checking": "На проверке",
66
"Up": "Активный",
77
"Down": "Недоступный",
8+
"Busy": "Занят",
89
"Type: backup": "Тип: запасной",
910
"Total downtime:": "Простаивает",
1011
"Down since:": "Не доступен с"

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "angie-console-light",
3-
"version": "1.6.1",
3+
"version": "1.7.0",
44
"description": "Angie Console Light",
55
"main": "index.js",
66
"scripts": {

src/calculators/factories.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export function handlePeer(upstreamsKey, STATS, previousState, upstream, peer) {
5353
break;
5454
case 'unavail':
5555
case 'unhealthy':
56+
case 'busy':
5657
STATS.servers.failed++;
5758
STATS.failures.increment(upstream.name);
5859
upstream.stats.failed++;
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
*
3+
* Copyright 2023-present, Web Server LLC
4+
* Copyright 2017-present, Nginx, Inc.
5+
* Copyright 2017-present, Ivan Poluyanov
6+
* Copyright 2017-present, Igor Meleshchenko
7+
* All rights reserved.
8+
*
9+
*/
10+
import React from 'react';
11+
import { shallow } from 'enzyme';
12+
import HumanReadableBytes from '../human-readable-bytes';
13+
import tooltips from '#/tooltips';
14+
15+
describe('<HumanReadableBytes />', () => {
16+
it('renders value and tooltip when value > 1023', () => {
17+
const initialValue = 2000;
18+
let tooltipText;
19+
jest
20+
.spyOn(tooltips, 'useTooltip')
21+
.mockClear()
22+
.mockImplementation((value) => {
23+
tooltipText = value;
24+
});
25+
26+
const wrapper = shallow(<HumanReadableBytes value={initialValue} />);
27+
const outputText = wrapper.find('span').text();
28+
29+
expect(outputText).toBe('1.95 KiB');
30+
expect(tooltipText).toBe(`${initialValue} B`);
31+
});
32+
33+
it('should render 0 when input value prop is not set', () => {
34+
const wrapper = shallow(<HumanReadableBytes />);
35+
const outputText = wrapper.find('span').text();
36+
37+
expect(outputText).toBe('0');
38+
});
39+
40+
it('renders value with postfix', () => {
41+
const initialValue = 2000;
42+
const postfix = 'postfix';
43+
let tooltipText;
44+
jest
45+
.spyOn(tooltips, 'useTooltip')
46+
.mockClear()
47+
.mockImplementation((input) => {
48+
tooltipText = input;
49+
});
50+
51+
const wrapper = shallow(<HumanReadableBytes value={initialValue} postfix={postfix} />);
52+
const outputText = wrapper.find('span').text();
53+
54+
expect(outputText).toBe(`1.95 KiB${postfix}`);
55+
expect(tooltipText).toBe(`${initialValue} B${postfix}`);
56+
});
57+
58+
it('wont render tooltip when value <= 1023', () => {
59+
const initialValue = 500;
60+
let tooltipComponent;
61+
jest
62+
.spyOn(tooltips, 'useTooltip')
63+
.mockClear()
64+
.mockImplementation((component) => {
65+
tooltipComponent = component;
66+
});
67+
const wrapper = shallow(<HumanReadableBytes value={initialValue} />);
68+
const outputText = wrapper.find('span').text();
69+
70+
expect(outputText).toBe(`${initialValue} B`);
71+
expect(tooltipComponent).toBe(undefined);
72+
});
73+
});
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
*
3+
* Copyright 2023-present, Web Server LLC
4+
* Copyright 2017-present, Nginx, Inc.
5+
* Copyright 2017-present, Ivan Poluyanov
6+
* Copyright 2017-present, Igor Meleshchenko
7+
* All rights reserved.
8+
*
9+
*/
10+
import React from 'react';
11+
import { withNamespaces } from 'react-i18next';
12+
import utils from '#/utils';
13+
import tooltips from '#/tooltips/index.jsx';
14+
15+
class HumanReadableBytes extends React.Component {
16+
formatReadableBytes(value, maxMeasurementUnit) {
17+
const { t } = this.props;
18+
return utils.formatReadableBytes(
19+
value,
20+
t(maxMeasurementUnit),
21+
utils.translateReadableBytesUnits({ t })
22+
);
23+
}
24+
25+
render() {
26+
const { value = 0, measurementUnit, postfix = '' } = this.props;
27+
28+
const readableValue = `${this.formatReadableBytes(value, measurementUnit)}${postfix}`;
29+
const bytesValue = `${this.formatReadableBytes(value, 'B')}${postfix}`;
30+
31+
return (
32+
(value > 1023) ?
33+
(
34+
<span {...tooltips.useTooltip(bytesValue, 'hint')}>
35+
{readableValue}
36+
</span>
37+
) :
38+
(
39+
<span>{readableValue}</span>
40+
)
41+
);
42+
}
43+
}
44+
45+
export default withNamespaces('common')(HumanReadableBytes);

src/components/pages/__test__/streamzones.test.jsx

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { shallow } from 'enzyme';
1212
import { StreamZones } from '../streamzones.jsx';
1313
import styles from '../../table/style.css';
1414
import utils from '../../../utils';
15+
import HumanReadableBytes from '#/components/human-readable-bytes/human-readable-bytes';
1516

1617
describe('<StreamZones Page />', () => {
1718
describe('render()', () => {
@@ -40,7 +41,7 @@ describe('<StreamZones Page />', () => {
4041
it('zones row', () => {
4142
jest.spyOn(utils, 'formatReadableBytes').mockClear().mockImplementation(a => a);
4243

43-
const server_zones = new Map([
44+
const server_zones = [
4445
['test', {
4546
processing: 100,
4647
connections: 23,
@@ -66,7 +67,7 @@ describe('<StreamZones Page />', () => {
6667
'4xxChanged': false,
6768
'5xxChanged': true
6869
}]
69-
]);
70+
];
7071
const wrapper = shallow(<StreamZones data={{ server_zones }} />);
7172
const rows = wrapper.find('tbody tr');
7273
let cells = rows.at(0).find('td');
@@ -106,26 +107,24 @@ describe('<StreamZones Page />', () => {
106107
expect(cell.prop('className')).toBe(styles.bdr);
107108
// row 1, cell 8, text
108109
expect(cell.text()).toBe('86');
110+
111+
const row = 0;
112+
// row 1, cell 9
109113
cell = cells.at(8);
110-
// row 1, cell 9, className
111114
expect(cell.prop('className')).toBe(styles.px60);
112-
// row 1, cell 9, text
113-
expect(cell.text()).toBe('333');
115+
expect(cell.find(HumanReadableBytes).props().value).toBe(server_zones[row][1].sent_s);
116+
// row 1, cell 10
114117
cell = cells.at(9);
115-
// row 1, cell 10, className
116118
expect(cell.prop('className')).toBe(styles.px60);
117-
// row 1, cell 10, text
118-
expect(cell.text()).toBe('0');
119+
expect(cell.find(HumanReadableBytes).props().value).toBe(server_zones[row][1].rcvd_s);
120+
// row 1, cell 11
119121
cell = cells.at(10);
120-
// row 1, cell 11, className
121122
expect(cell.prop('className')).toBe(styles.px60);
122-
// row 1, cell 11, text
123-
expect(cell.text()).toBe('950');
123+
expect(cell.find(HumanReadableBytes).props().value).toBe(server_zones[row][1].sent);
124+
// row 1, cell 12
124125
cell = cells.at(11);
125-
// row 1, cell 12, className
126126
expect(cell.prop('className')).toBe(`${ styles.px60 } ${ styles.bdr }`);
127-
// row 1, cell 12, text
128-
expect(cell.text()).toBe('3');
127+
expect(cell.find(HumanReadableBytes).props().value).toBe(server_zones[row][1].received);
129128

130129
// TODO: Add tests for SSL stat cells
131130

0 commit comments

Comments
 (0)