Skip to content

Commit fd055ca

Browse files
committed
Merge branch 'main' into feature/O2B-1503/lhcfills-fill-numbers-filter
2 parents 1e3f503 + 5081ae9 commit fd055ca

10 files changed

Lines changed: 275 additions & 50 deletions

File tree

lib/domain/enums/StatusAcronyms.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const statusAcronyms = Object.freeze({
1919
RUNNING: 'R',
2020
ERROR: 'E',
2121
DESTROYED: 'X',
22+
DONE: 'X',
2223
});
2324

2425
exports.statusAcronyms = statusAcronyms;

lib/public/components/environments/environmentStatusHistoryComponent.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ export const environmentStatusHistoryLegendComponent = () =>
2525
h('h5', 'Status History Legend'),
2626
Object.keys(StatusAcronym).map((status) =>
2727
h('.flex-row.justify-between', [
28-
h('', status),
29-
h('', StatusAcronym[status]),
28+
coloredEnvironmentStatusComponent(status),
29+
h('', coloredEnvironmentStatusComponent(status, StatusAcronym[status])),
3030
])),
3131
]);
3232

lib/public/domain/enums/statusAcronym.mjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ export const StatusAcronym = Object.freeze({
1818
CONFIGURED: 'C',
1919
RUNNING: 'R',
2020
ERROR: 'E',
21-
MIXED: 'M',
2221
DESTROYED: 'X',
2322
DONE: 'X',
2423
});

lib/public/views/Environments/ActiveColumns/environmentsActiveColumns.js

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import { environmentStatusHistoryLegendComponent } from '../../../components/env
2424
import { infoTooltip } from '../../../components/common/popover/infoTooltip.js';
2525
import { aliEcsEnvironmentLinkComponent } from '../../../components/common/externalLinks/aliEcsEnvironmentLinkComponent.js';
2626
import { StatusAcronym } from '../../../domain/enums/statusAcronym.mjs';
27+
import { timeRangeFilter } from '../../../components/Filters/common/filters/timeRangeFilter.js';
28+
import { checkboxes } from '../../../components/Filters/common/filters/checkboxFilter.js';
2729
import { rawTextFilter } from '../../../components/Filters/common/filters/rawTextFilter.js';
2830

2931
/**
@@ -73,6 +75,17 @@ export const environmentsActiveColumns = {
7375
size: 'w-10',
7476
format: formatRunsList,
7577
balloon: true,
78+
79+
/**
80+
* Run numbers filter component
81+
*
82+
* @param {EnvironmentOverviewModel} environmentOverviewModel the environment overview model
83+
* @return {Component} the filter component
84+
*/
85+
filter: (environmentOverviewModel) => rawTextFilter(
86+
environmentOverviewModel.filteringModel.get('runNumbers'),
87+
{ classes: ['w-100'], placeholder: 'e.g. 553203, 553221, ...' },
88+
),
7689
},
7790
updatedAt: {
7891
name: 'Last Update',
@@ -83,10 +96,18 @@ export const environmentsActiveColumns = {
8396
},
8497
createdAt: {
8598
name: 'Created At',
86-
visible: false,
99+
visible: true,
87100
sortable: false,
88101
size: 'w-10',
89102
format: (timestamp) => formatTimestamp(timestamp, false),
103+
104+
/**
105+
* CreatedAt filter component
106+
*
107+
* @param {EnvironmentOverviewModel} environmentOverviewModel the environment overview model
108+
* @return {Component} the filter component
109+
*/
110+
filter: (environmentOverviewModel) => timeRangeFilter(environmentOverviewModel.filteringModel.get('created')),
90111
},
91112
status: {
92113
name: 'Current Status',
@@ -95,6 +116,14 @@ export const environmentsActiveColumns = {
95116
size: 'w-10',
96117
noEllipsis: true,
97118
format: (_, environment) => displayEnvironmentStatus(environment),
119+
120+
/**
121+
* Status filter component
122+
*
123+
* @param {EnvironmentOverviewModel} environmentOverviewModel the environment overview model
124+
* @return {Component} the filter component
125+
*/
126+
filter: (environmentOverviewModel) => checkboxes(environmentOverviewModel.filteringModel.get('currentStatus').selectionModel),
98127
},
99128
historyItems: {
100129
name: h('.flex-row.g2.items-center', ['Status History', infoTooltip(environmentStatusHistoryLegendComponent())]),
@@ -107,5 +136,16 @@ export const environmentsActiveColumns = {
107136
coloredEnvironmentStatusComponent(status, StatusAcronym[status]),
108137
]).slice(1),
109138
balloon: true,
139+
140+
/**
141+
* Status history filter component
142+
*
143+
* @param {EnvironmentOverviewModel} environmentOverviewModel the environment overview model
144+
* @return {Component} the filter component
145+
*/
146+
filter: (environmentOverviewModel) => rawTextFilter(
147+
environmentOverviewModel.filteringModel.get('statusHistory'),
148+
{ classes: ['w-100'], placeholder: 'e.g. D-R-X' },
149+
),
110150
},
111151
};

lib/public/views/Environments/Overview/EnvironmentOverviewModel.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@
1414
import { buildUrl } from '/js/src/index.js';
1515
import { FilteringModel } from '../../../components/Filters/common/FilteringModel.js';
1616
import { OverviewPageModel } from '../../../models/OverviewModel.js';
17+
import { TimeRangeInputModel } from '../../../components/Filters/common/filters/TimeRangeInputModel.js';
18+
import { SelectionFilterModel } from '../../../components/Filters/common/filters/SelectionFilterModel.js';
1719
import { RawTextFilterModel } from '../../../components/Filters/common/filters/RawTextFilterModel.js';
1820
import { debounce } from '../../../utilities/debounce.js';
21+
import { coloredEnvironmentStatusComponent } from '../ColoredEnvironmentStatusComponent.js';
22+
import { StatusAcronym } from '../../../domain/enums/statusAcronym.mjs';
1923

2024
/**
2125
* Environment overview page model
@@ -29,6 +33,16 @@ export class EnvironmentOverviewModel extends OverviewPageModel {
2933
super();
3034

3135
this._filteringModel = new FilteringModel({
36+
created: new TimeRangeInputModel(),
37+
runNumbers: new RawTextFilterModel(),
38+
statusHistory: new RawTextFilterModel(),
39+
currentStatus: new SelectionFilterModel({
40+
availableOptions: Object.keys(StatusAcronym).map((status) => ({
41+
value: status,
42+
label: coloredEnvironmentStatusComponent(status),
43+
rawLabel: status,
44+
})),
45+
}),
3246
ids: new RawTextFilterModel(),
3347
});
3448

lib/usecases/environment/GetAllEnvironmentsUseCase.js

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,10 @@ class GetAllEnvironmentsUseCase {
126126
}
127127

128128
if (statusHistory) {
129-
// Split the string into separate characters
130-
const historyItems = statusHistory.split('');
129+
// Check if status history ends with 'X' and remove it if present to handle the special case later
130+
const containsX = statusHistory.endsWith('X');
131+
const cleanedStatusHistory = containsX ? statusHistory.slice(0, -1) : statusHistory;
132+
const historyItems = cleanedStatusHistory.split('');
131133

132134
// Swap the acronyms with the status (=acronym -> status)
133135
const acronymToStatus = {};
@@ -145,17 +147,38 @@ class GetAllEnvironmentsUseCase {
145147
}
146148
}
147149

148-
// Filter the environments by status history using the subquery
149-
filterQueryBuilder.literalWhere(
150-
`${ENVIRONMENT_STATUS_HISTORY_SUBQUERY} = :statusFilters`,
151-
// Create a string of the status filters separated by a comma
152-
{ statusFilters: statusFilters.join(',') },
153-
);
150+
if (containsX) {
151+
const statusFiltersWithDestroyed = [...statusFilters, 'DESTROYED'].join(',');
152+
const statusFiltersWithDone = [...statusFilters, 'DONE'].join(',');
153+
154+
/*
155+
* Use OR condition to match subsequences ending with either DESTROYED or DONE
156+
* Filter the environments by using LIKE for subsequence matching
157+
*/
158+
filterQueryBuilder.literalWhere(
159+
`(${ENVIRONMENT_STATUS_HISTORY_SUBQUERY} LIKE :statusFiltersWithDestroyed OR ` +
160+
`${ENVIRONMENT_STATUS_HISTORY_SUBQUERY} LIKE :statusFiltersWithDone)`,
161+
{
162+
statusFiltersWithDestroyed: `%${statusFiltersWithDestroyed}`,
163+
statusFiltersWithDone: `%${statusFiltersWithDone}`,
164+
},
165+
);
154166

155-
filterQueryBuilder.includeAttribute({
156-
query: ENVIRONMENT_STATUS_HISTORY_SUBQUERY,
157-
alias: 'statusHistory',
158-
});
167+
filterQueryBuilder.includeAttribute({
168+
query: ENVIRONMENT_STATUS_HISTORY_SUBQUERY,
169+
alias: 'statusHistory',
170+
});
171+
} else {
172+
filterQueryBuilder.literalWhere(
173+
`${ENVIRONMENT_STATUS_HISTORY_SUBQUERY} LIKE :statusFilters`,
174+
{ statusFilters: `%${statusFilters.join(',')}%` },
175+
);
176+
177+
filterQueryBuilder.includeAttribute({
178+
query: ENVIRONMENT_STATUS_HISTORY_SUBQUERY,
179+
alias: 'statusHistory',
180+
});
181+
}
159182
}
160183

161184
if (runNumbersExpression) {

package-lock.json

Lines changed: 32 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,13 @@
5151
"chai": "4.5.0",
5252
"date-and-time": "3.6.0",
5353
"eslint": "^9.37.0",
54-
"eslint-plugin-jsdoc": "^61.4.1",
54+
"eslint-plugin-jsdoc": "^61.5.0",
5555
"globals": "^16.5.0",
5656
"js-yaml": "4.1.1",
5757
"mocha": "11.7.0",
5858
"nodemon": "3.1.3",
5959
"nyc": "17.1.0",
60-
"puppeteer": "24.31.0",
60+
"puppeteer": "24.33.0",
6161
"puppeteer-to-istanbul": "1.4.0",
6262
"sequelize-cli": "6.6.0",
6363
"sinon": "21.0.0",

test/api/environments.test.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,15 @@ module.exports = () => {
171171
expect(withChar[1].id).to.be.equal(withoutChar[1].id);
172172
});
173173

174+
it('should successfully filter environments on status history with a partial sequence', async () => {
175+
const response = await request(server).get('/api/environments?filter[statusHistory]=D-E');
176+
177+
expect(response.status).to.equal(200);
178+
const environments = response.body.data;
179+
expect(environments.length).to.be.equal(1);
180+
expect(environments[0].id).to.be.equal('KGIS12DS');
181+
});
182+
174183
it('should successfully filter environments status history with limit', async () => {
175184
const response = await request(server).get('/api/environments?filter[statusHistory]=SE&page[limit]=1');
176185

0 commit comments

Comments
 (0)