Skip to content

Commit 276f027

Browse files
committed
feat(Storage): usage filter
1 parent a35067f commit 276f027

File tree

2 files changed

+100
-19
lines changed

2 files changed

+100
-19
lines changed

src/containers/Storage/Storage.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import DataTable from '@yandex-cloud/react-data-table';
66
import {RadioButton, Label} from '@yandex-cloud/uikit';
77

88
import {StorageFilter} from './StorageFilter';
9+
import {UsageFilter} from './UsageFilter';
910
import {AutoFetcher} from '../../utils/autofetcher';
1011
import {TableSkeleton} from '../../components/TableSkeleton/TableSkeleton';
1112

@@ -16,12 +17,14 @@ import {
1617
VisibleEntities,
1718
setVisibleEntities,
1819
setStorageFilter,
20+
setUsageFilter,
1921
getNodesObject,
2022
StorageTypes,
2123
setStorageType,
2224
VisibleEntitiesTitles,
2325
getStoragePoolsGroupsCount,
2426
getStorageNodesCount,
27+
getUsageFilterOptions,
2528
} from '../../store/reducers/storage';
2629
import {getNodesList} from '../../store/reducers/clusterNodes';
2730
import StorageGroups from './StorageGroups/StorageGroups';
@@ -239,6 +242,9 @@ class Storage extends React.Component {
239242
setStorageFilter,
240243
visibleEntities,
241244
storageType,
245+
usageFilter,
246+
setUsageFilter,
247+
usageFilterOptions,
242248
} = this.props;
243249

244250
return (
@@ -270,6 +276,16 @@ class Storage extends React.Component {
270276
{StorageTypes.nodes}
271277
</RadioButton.Option>
272278
</RadioButton>
279+
280+
{storageType === StorageTypes.groups && (
281+
<UsageFilter
282+
value={usageFilter}
283+
onChange={setUsageFilter}
284+
groups={usageFilterOptions}
285+
disabled={usageFilterOptions.length === 0}
286+
/>
287+
)}
288+
273289
<Label theme="info" size="m">
274290
{this.renderEntitiesCount()}
275291
</Label>
@@ -305,6 +321,7 @@ function mapStateToProps(state) {
305321
visible: visibleEntities,
306322
type: storageType,
307323
filter,
324+
usageFilter,
308325
} = state.storage;
309326

310327
return {
@@ -319,13 +336,16 @@ function mapStateToProps(state) {
319336
visibleEntities,
320337
storageType,
321338
filter,
339+
usageFilter,
340+
usageFilterOptions: getUsageFilterOptions(state),
322341
};
323342
}
324343

325344
const mapDispatchToProps = {
326345
getStorageInfo,
327346
setInitialState,
328347
setStorageFilter,
348+
setUsageFilter,
329349
setVisibleEntities: setVisibleEntities,
330350
getNodesList,
331351
setStorageType,

src/store/reducers/storage.js

Lines changed: 80 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import '../../services/api';
33
import _ from 'lodash';
44
import {createSelector} from 'reselect';
55
import {calcUptime} from '../../utils';
6+
import {getUsage} from '../../containers/Storage/utils';
67

78
export const VisibleEntities = {
89
All: 'All',
@@ -24,13 +25,15 @@ export const StorageTypes = {
2425
const FETCH_STORAGE = createRequestActionTypes('storage', 'FETCH_STORAGE');
2526
const SET_INITIAL = 'storage/SET_INITIAL';
2627
const SET_FILTER = 'storage/SET_FILTER';
28+
const SET_USAGE_FILTER = 'storage/SET_USAGE_FILTER';
2729
const SET_VISIBLE_GROUPS = 'storage/SET_VISIBLE_GROUPS';
2830
const SET_STORAGE_TYPE = 'storage/SET_STORAGE_TYPE';
2931

3032
const initialState = {
3133
loading: true,
3234
wasLoaded: false,
3335
filter: '',
36+
usageFilter: [],
3437
visible: VisibleEntities.Missing,
3538
type: StorageTypes.groups,
3639
};
@@ -70,6 +73,12 @@ const storage = function z(state = initialState, action) {
7073
filter: action.data,
7174
};
7275
}
76+
case SET_USAGE_FILTER: {
77+
return {
78+
...state,
79+
usageFilter: action.data,
80+
};
81+
}
7382
case SET_VISIBLE_GROUPS: {
7483
return {
7584
...state,
@@ -82,6 +91,8 @@ const storage = function z(state = initialState, action) {
8291
return {
8392
...state,
8493
type: action.data,
94+
filter: '',
95+
usageFilter: [],
8596
wasLoaded: false,
8697
error: undefined,
8798
};
@@ -117,6 +128,14 @@ export function setStorageFilter(value) {
117128
data: value,
118129
};
119130
}
131+
132+
export function setUsageFilter(value) {
133+
return {
134+
type: SET_USAGE_FILTER,
135+
data: value,
136+
};
137+
}
138+
120139
export function setVisibleEntities(value) {
121140
return {
122141
type: SET_VISIBLE_GROUPS,
@@ -135,6 +154,7 @@ export const getStorageNodesCount = (state) => ({
135154
found: state.storage.data?.FoundNodes || 0,
136155
});
137156
export const getStorageFilter = (state) => state.storage.filter;
157+
export const getUsageFilter = (state) => state.storage.usageFilter;
138158
export const getVisibleEntities = (state) => state.storage.visible;
139159
export const getStorageType = (state) => state.storage.type;
140160
export const getNodesObject = (state) =>
@@ -271,26 +291,67 @@ export const getVisibleEntitiesList = createSelector(
271291
},
272292
);
273293

274-
export const getFilteredEntities = createSelector(
275-
[getStorageFilter, getStorageType, getVisibleEntitiesList],
276-
(filter, type, entities) => {
277-
const cleanedFilter = filter.trim().toLowerCase();
278-
if (!cleanedFilter) {
279-
return entities;
280-
} else {
281-
return _.filter(entities, (e) => {
282-
if (type === StorageTypes.groups) {
283-
return (
284-
e.PoolName.toLowerCase().includes(cleanedFilter) ||
285-
e.GroupID?.toString().includes(cleanedFilter)
286-
);
287-
}
288-
return (
289-
e.NodeId.toString().includes(cleanedFilter) ||
290-
e.FQDN.toLowerCase().includes(cleanedFilter)
291-
);
292-
});
294+
const filterByText = (entities, type, text) => {
295+
const cleanedFilter = text.trim().toLowerCase();
296+
297+
if (!cleanedFilter) {
298+
return entities;
299+
}
300+
301+
return entities.filter((entity) => {
302+
if (type === StorageTypes.groups) {
303+
return (
304+
entity.PoolName.toLowerCase().includes(cleanedFilter) ||
305+
entity.GroupID?.toString().includes(cleanedFilter)
306+
);
293307
}
308+
309+
return (
310+
entity.NodeId.toString().includes(cleanedFilter) ||
311+
entity.FQDN.toLowerCase().includes(cleanedFilter)
312+
);
313+
});
314+
};
315+
316+
const filterByUsage = (entities, usage) => {
317+
if (!Array.isArray(usage) || usage.length === 0) {
318+
return entities;
319+
}
320+
321+
return entities.filter((entity) => {
322+
const entityUsage = getUsage(entity, 5);
323+
return usage.some((val) => Number(val) <= entityUsage && entityUsage < Number(val) + 5);
324+
});
325+
};
326+
327+
export const getFilteredEntities = createSelector(
328+
[getStorageFilter, getUsageFilter, getStorageType, getVisibleEntitiesList],
329+
(textFilter, usageFilter, type, entities) => {
330+
let result = entities;
331+
result = filterByText(result, type, textFilter);
332+
result = filterByUsage(result, usageFilter);
333+
return result;
334+
},
335+
);
336+
337+
export const getUsageFilterOptions = createSelector(
338+
getVisibleEntitiesList,
339+
(entities) => {
340+
const items = {};
341+
342+
entities.forEach((entity) => {
343+
const usage = getUsage(entity, 5);
344+
345+
if (!Object.hasOwn(items, usage)) {
346+
items[usage] = 0;
347+
}
348+
349+
items[usage] += 1;
350+
});
351+
352+
return Object.entries(items)
353+
.map(([threshold, count]) => ({threshold, count}))
354+
.sort((a, b) => b.threshold - a.threshold);
294355
},
295356
);
296357

0 commit comments

Comments
 (0)