api,server,ui: allow listing events by state (#11355)

* api,server,ui: allow listing events by state

This change allows listing events by a particular state - Created, Scheduled, Started, Completed.
A new parameter - state has been added to the listEvents API and corresponding changes have been added in the UI.

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>

* Update api/src/main/java/org/apache/cloudstack/api/command/user/event/ListEventsCmd.java

---------

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Co-authored-by: Suresh Kumar Anaparti <sureshkumar.anaparti@gmail.com>
This commit is contained in:
Abhishek Kumar 2025-07-31 19:22:15 +05:30 committed by GitHub
parent adccdf2c7b
commit a60c8cab14
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 44 additions and 2 deletions

View File

@ -73,6 +73,9 @@ public class ListEventsCmd extends BaseListProjectAndAccountResourcesCmd {
@Parameter(name = ApiConstants.ARCHIVED, type = CommandType.BOOLEAN, description = "true to list archived events otherwise false", since="4.19.0")
private Boolean archived;
@Parameter(name = ApiConstants.STATE, type = CommandType.STRING, description = "The state of the events", since="4.21.0")
private String state;
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@ -121,6 +124,10 @@ public class ListEventsCmd extends BaseListProjectAndAccountResourcesCmd {
return archived != null && archived;
}
public String getState() {
return state;
}
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////

View File

@ -243,6 +243,7 @@ import com.cloud.dc.dao.HostPodDao;
import com.cloud.domain.Domain;
import com.cloud.domain.DomainVO;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.Event;
import com.cloud.event.EventVO;
import com.cloud.event.dao.EventDao;
import com.cloud.event.dao.EventJoinDao;
@ -868,6 +869,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
Long startId = cmd.getStartId();
final String resourceUuid = cmd.getResourceId();
final String resourceTypeStr = cmd.getResourceType();
final String stateStr = cmd.getState();
ApiCommandResourceType resourceType = null;
Long resourceId = null;
if (resourceTypeStr != null) {
@ -897,6 +899,13 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
accountMgr.checkAccess(CallContext.current().getCallingAccount(), SecurityChecker.AccessType.ListEntry, entity.getAccountId() == caller.getId(), entity);
}
}
Event.State state = null;
if (StringUtils.isNotBlank(stateStr)) {
state = EnumUtils.getEnum(Event.State.class, stateStr);
if (state == null) {
throw new InvalidParameterValueException(String.format("Invalid %s specified: %s", ApiConstants.STATE, stateStr));
}
}
Ternary<Long, Boolean, ListProjectResourcesCriteria> domainIdRecursiveListProject = new Ternary<>(cmd.getDomainId(), cmd.isRecursive(), null);
accountMgr.buildACLSearchParameters(caller, id, cmd.getAccountName(), cmd.getProjectId(), permittedAccounts, domainIdRecursiveListProject, cmd.listAll(), false);
@ -920,7 +929,7 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
eventSearchBuilder.and("createDateB", eventSearchBuilder.entity().getCreateDate(), SearchCriteria.Op.BETWEEN);
eventSearchBuilder.and("createDateG", eventSearchBuilder.entity().getCreateDate(), SearchCriteria.Op.GTEQ);
eventSearchBuilder.and("createDateL", eventSearchBuilder.entity().getCreateDate(), SearchCriteria.Op.LTEQ);
eventSearchBuilder.and("state", eventSearchBuilder.entity().getState(), SearchCriteria.Op.NEQ);
eventSearchBuilder.and("state", eventSearchBuilder.entity().getState(), SearchCriteria.Op.EQ);
eventSearchBuilder.or("startId", eventSearchBuilder.entity().getStartId(), SearchCriteria.Op.EQ);
eventSearchBuilder.and("createDate", eventSearchBuilder.entity().getCreateDate(), SearchCriteria.Op.BETWEEN);
eventSearchBuilder.and("displayEvent", eventSearchBuilder.entity().isDisplay(), SearchCriteria.Op.EQ);
@ -989,6 +998,10 @@ public class QueryManagerImpl extends MutualExclusiveIdsManagerBase implements Q
sc.setParameters("archived", cmd.getArchived());
}
if (state != null) {
sc.setParameters("state", state);
}
Pair<List<Long>, Integer> eventPair;
// event_view will not have duplicate rows for each event, so
// searchAndCount should be good enough.

View File

@ -573,6 +573,7 @@
"label.communities": "Communities",
"label.community": "Community",
"label.complete": "Complete",
"label.completed": "Completed",
"label.compute": "Compute",
"label.compute.offerings": "Compute Offerings",
"label.compute.offering.for.sharedfs.instance": "Compute Offering for Instance",
@ -2157,6 +2158,7 @@
"label.scaleup.policy": "ScaleUp policy",
"label.scaling": "Scaling",
"label.schedule": "Schedule",
"label.scheduled": "Scheduled",
"label.schedule.add": "Add schedule",
"label.scheduled.backups": "Scheduled backups",
"label.schedules": "Schedules",
@ -2328,6 +2330,7 @@
"label.standard.us.keyboard": "Standard (US) keyboard",
"label.start": "Start",
"label.startasn": "Start AS Number",
"label.started": "Started",
"label.start.date": "Start date",
"label.start.date.and.time": "Start date and time",
"label.start.ip": "Start IP",

View File

@ -1380,6 +1380,25 @@ export default {
name: 'label.disabled'
}
]
} else if (this.apiName.indexOf('listEvents') > -1) {
state = [
{
id: 'Created',
name: 'label.created'
},
{
id: 'Scheduled',
name: 'label.scheduled'
},
{
id: 'Started',
name: 'label.started'
},
{
id: 'Completed',
name: 'label.completed'
}
]
}
return state
},

View File

@ -32,7 +32,7 @@ export default {
return fields
},
details: ['username', 'id', 'description', 'resourcetype', 'resourceid', 'state', 'level', 'type', 'account', 'domain', 'created'],
searchFilters: ['level', 'domainid', 'account', 'keyword', 'resourcetype'],
searchFilters: ['level', 'domainid', 'account', 'keyword', 'resourcetype', 'state'],
related: [{
name: 'event',
title: 'label.event.timeline',