Skip to content

Commit d8cfea1

Browse files
feat(Storage): add nodes uptime filter
1 parent 56b2701 commit d8cfea1

File tree

6 files changed

+114
-15
lines changed

6 files changed

+114
-15
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import {RadioButton} from '@gravity-ui/uikit';
2+
3+
import {NodesUptimeFilterValues, NodesUptimeFilterTitles} from '../../utils/nodes';
4+
5+
interface UptimeFilterProps {
6+
value: keyof typeof NodesUptimeFilterValues;
7+
onChange: (value: string) => void;
8+
}
9+
10+
export const UptimeFilter = ({value, onChange}: UptimeFilterProps) => {
11+
return (
12+
<RadioButton value={value} onUpdate={onChange}>
13+
<RadioButton.Option value={NodesUptimeFilterValues.All}>
14+
{NodesUptimeFilterTitles[NodesUptimeFilterValues.All]}
15+
</RadioButton.Option>
16+
<RadioButton.Option value={NodesUptimeFilterValues.SmallUptime}>
17+
{NodesUptimeFilterTitles[NodesUptimeFilterValues.SmallUptime]}
18+
</RadioButton.Option>
19+
</RadioButton>
20+
);
21+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './UptimeFilter';

src/containers/Storage/Storage.js

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import {RadioButton, Label} from '@gravity-ui/uikit';
88
import {Search} from '../../components/Search';
99
import {UsageFilter} from './UsageFilter';
1010
import {AutoFetcher} from '../../utils/autofetcher';
11+
import {NodesUptimeFilterValues} from '../../utils/nodes';
1112
import {TableSkeleton} from '../../components/TableSkeleton/TableSkeleton';
13+
import {UptimeFilter} from '../../components/UptimeFIlter';
1214
import {AccessDenied} from '../../components/Errors/403';
1315

1416
import {
@@ -22,6 +24,7 @@ import {
2224
getNodesObject,
2325
StorageTypes,
2426
setStorageType,
27+
setNodesUptimeFilter,
2528
VisibleEntitiesTitles,
2629
getStoragePoolsGroupsCount,
2730
getStorageNodesCount,
@@ -66,6 +69,8 @@ class Storage extends React.Component {
6669
setHeader: PropTypes.func,
6770
tenant: PropTypes.string,
6871
nodeId: PropTypes.string,
72+
nodesUptimeFilter: PropTypes.string,
73+
setNodesUptimeFilter: PropTypes.func,
6974
};
7075

7176
componentDidMount() {
@@ -201,6 +206,15 @@ class Storage extends React.Component {
201206
setStorageType(value);
202207
};
203208

209+
onUptimeFilterChange = (value) => {
210+
this.props.setNodesUptimeFilter(value);
211+
};
212+
213+
onShowAllNodes = () => {
214+
this.onGroupVisibilityChange(VisibleEntities.All);
215+
this.onUptimeFilterChange(NodesUptimeFilterValues.All);
216+
};
217+
204218
renderEntitiesCount() {
205219
const {storageType, groupsCount, nodesCount, flatListStorageEntities, loading, wasLoaded} =
206220
this.props;
@@ -230,6 +244,7 @@ class Storage extends React.Component {
230244
visibleEntities,
231245
storageType,
232246
usageFilter,
247+
nodesUptimeFilter,
233248
setUsageFilter,
234249
usageFilterOptions,
235250
} = this.props;
@@ -247,6 +262,16 @@ class Storage extends React.Component {
247262
value={filter}
248263
/>
249264
</div>
265+
266+
<RadioButton value={storageType} onUpdate={this.onStorageTypeChange}>
267+
<RadioButton.Option value={StorageTypes.groups}>
268+
{StorageTypes.groups}
269+
</RadioButton.Option>
270+
<RadioButton.Option value={StorageTypes.nodes}>
271+
{StorageTypes.nodes}
272+
</RadioButton.Option>
273+
</RadioButton>
274+
250275
<RadioButton value={visibleEntities} onUpdate={this.onGroupVisibilityChange}>
251276
<RadioButton.Option value={VisibleEntities.Missing}>
252277
{VisibleEntitiesTitles[VisibleEntities.Missing]}
@@ -259,14 +284,9 @@ class Storage extends React.Component {
259284
</RadioButton.Option>
260285
</RadioButton>
261286

262-
<RadioButton value={storageType} onUpdate={this.onStorageTypeChange}>
263-
<RadioButton.Option value={StorageTypes.groups}>
264-
{StorageTypes.groups}
265-
</RadioButton.Option>
266-
<RadioButton.Option value={StorageTypes.nodes}>
267-
{StorageTypes.nodes}
268-
</RadioButton.Option>
269-
</RadioButton>
287+
{storageType === StorageTypes.nodes && (
288+
<UptimeFilter value={nodesUptimeFilter} onChange={this.onUptimeFilterChange} />
289+
)}
270290

271291
{storageType === StorageTypes.groups && (
272292
<UsageFilter
@@ -314,6 +334,7 @@ function mapStateToProps(state) {
314334
type: storageType,
315335
filter,
316336
usageFilter,
337+
nodesUptimeFilter,
317338
} = state.storage;
318339

319340
return {
@@ -329,6 +350,7 @@ function mapStateToProps(state) {
329350
storageType,
330351
filter,
331352
usageFilter,
353+
nodesUptimeFilter,
332354
usageFilterOptions: getUsageFilterOptions(state),
333355
};
334356
}
@@ -339,6 +361,7 @@ const mapDispatchToProps = {
339361
setStorageFilter,
340362
setUsageFilter,
341363
setVisibleEntities: setVisibleEntities,
364+
setNodesUptimeFilter,
342365
getNodesList,
343366
setStorageType,
344367
setHeader,

src/store/reducers/storage.js

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
import {createRequestActionTypes, createApiRequest} from '../utils';
2-
import '../../services/api';
31
import _ from 'lodash';
42
import {createSelector} from 'reselect';
5-
import {calcUptime} from '../../utils';
3+
4+
import {calcUptime, calcUptimeInSeconds} from '../../utils';
65
import {getUsage} from '../../utils/storage';
6+
import {NodesUptimeFilterValues} from '../../utils/nodes';
77
import {getPDiskType} from '../../utils/pdisk';
8+
import {HOUR_IN_SECONDS} from '../../utils/constants';
9+
import '../../services/api';
10+
11+
import {createRequestActionTypes, createApiRequest} from '../utils';
812

913
export const VisibleEntities = {
1014
All: 'All',
@@ -29,13 +33,15 @@ const SET_FILTER = 'storage/SET_FILTER';
2933
const SET_USAGE_FILTER = 'storage/SET_USAGE_FILTER';
3034
const SET_VISIBLE_GROUPS = 'storage/SET_VISIBLE_GROUPS';
3135
const SET_STORAGE_TYPE = 'storage/SET_STORAGE_TYPE';
36+
const SET_NODES_UPTIME_FILTER = 'storage/SET_NODES_UPTIME_FILTER';
3237

3338
const initialState = {
3439
loading: true,
3540
wasLoaded: false,
3641
filter: '',
3742
usageFilter: [],
3843
visible: VisibleEntities.Missing,
44+
nodesUptimeFilter: NodesUptimeFilterValues.All,
3945
type: StorageTypes.groups,
4046
};
4147

@@ -93,6 +99,13 @@ const storage = (state = initialState, action) => {
9399
error: undefined,
94100
};
95101
}
102+
103+
case SET_NODES_UPTIME_FILTER: {
104+
return {
105+
...state,
106+
nodesUptimeFilter: action.data,
107+
};
108+
}
96109
case SET_STORAGE_TYPE: {
97110
return {
98111
...state,
@@ -149,6 +162,13 @@ export function setVisibleEntities(value) {
149162
};
150163
}
151164

165+
export function setNodesUptimeFilter(value) {
166+
return {
167+
type: SET_NODES_UPTIME_FILTER,
168+
data: value,
169+
};
170+
}
171+
152172
export const getStoragePools = (state) => state.storage.data?.StoragePools;
153173
export const getStoragePoolsGroupsCount = (state) => ({
154174
total: state.storage.data?.TotalGroups || 0,
@@ -162,6 +182,7 @@ export const getStorageNodesCount = (state) => ({
162182
export const getStorageFilter = (state) => state.storage.filter;
163183
export const getUsageFilter = (state) => state.storage.usageFilter;
164184
export const getVisibleEntities = (state) => state.storage.visible;
185+
export const getNodesUptimeFilter = (state) => state.storage.nodesUptimeFilter;
165186
export const getStorageType = (state) => state.storage.type;
166187
export const getNodesObject = (state) =>
167188
_.reduce(
@@ -337,12 +358,32 @@ const filterByUsage = (entities, usage) => {
337358
});
338359
};
339360

361+
export const filterByUptime = (nodes = [], nodesUptimeFilter) => {
362+
if (nodesUptimeFilter === NodesUptimeFilterValues.All) {
363+
return nodes;
364+
}
365+
return nodes.filter(({StartTime}) => {
366+
return !StartTime || calcUptimeInSeconds(StartTime) < HOUR_IN_SECONDS;
367+
});
368+
};
369+
340370
export const getFilteredEntities = createSelector(
341-
[getStorageFilter, getUsageFilter, getStorageType, getVisibleEntitiesList],
342-
(textFilter, usageFilter, type, entities) => {
371+
[
372+
getStorageFilter,
373+
getUsageFilter,
374+
getStorageType,
375+
getNodesUptimeFilter,
376+
getVisibleEntitiesList,
377+
],
378+
(textFilter, usageFilter, type, nodesUptimeFilter, entities) => {
343379
let result = entities;
344380
result = filterByText(result, type, textFilter);
345381
result = filterByUsage(result, usageFilter);
382+
383+
if (type === StorageTypes.nodes) {
384+
result = filterByUptime(result, nodesUptimeFilter);
385+
}
386+
346387
return result;
347388
},
348389
);

src/utils/index.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,13 @@ export const formatDateTime = (value) => {
7979
return value > 0 ? new Date(Number(value)).toUTCString() : 'N/A';
8080
};
8181

82-
export const calcUptime = (milliseconds) => {
82+
export const calcUptimeInSeconds = (milliseconds) => {
8383
const currentDate = new Date();
84-
return formatUptime((currentDate - Number(milliseconds)) / 1000);
84+
return (currentDate - Number(milliseconds)) / 1000;
85+
};
86+
87+
export const calcUptime = (milliseconds) => {
88+
return formatUptime(calcUptimeInSeconds(milliseconds));
8589
};
8690

8791
// determine how many nodes have status Connected "true"

src/utils/nodes.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export const NodesUptimeFilterValues = {
2+
All: 'All',
3+
SmallUptime: 'SmallUptime',
4+
};
5+
6+
export const NodesUptimeFilterTitles = {
7+
[NodesUptimeFilterValues.All]: 'All',
8+
[NodesUptimeFilterValues.SmallUptime]: 'Uptime < 1h',
9+
};

0 commit comments

Comments
 (0)