Improve USB policy history with filters and pagination
- Fix bug where APPLYING status would not transition to APPLIED - Add status and date range filters to policy history - Add cursor-based pagination with "Load more" button - Use DateRangeButton component for date filtering - Reset filters and pagination when switching filters 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
5846c299ce
commit
873305fa7f
2 changed files with 212 additions and 48 deletions
|
|
@ -117,7 +117,9 @@ export const reportUsbPolicyStatus = mutation({
|
|||
.order("desc")
|
||||
.first()
|
||||
|
||||
if (latestEvent && latestEvent.status === "PENDING") {
|
||||
// Atualiza o evento se ainda nao foi finalizado (PENDING ou APPLYING)
|
||||
// Isso permite a transicao: PENDING -> APPLYING -> APPLIED/FAILED
|
||||
if (latestEvent && (latestEvent.status === "PENDING" || latestEvent.status === "APPLYING")) {
|
||||
await ctx.db.patch(latestEvent._id, {
|
||||
status: args.status,
|
||||
error: errorValue,
|
||||
|
|
@ -185,27 +187,57 @@ export const listUsbPolicyEvents = query({
|
|||
args: {
|
||||
machineId: v.id("machines"),
|
||||
limit: v.optional(v.number()),
|
||||
cursor: v.optional(v.number()),
|
||||
status: v.optional(v.string()),
|
||||
dateFrom: v.optional(v.number()),
|
||||
dateTo: v.optional(v.number()),
|
||||
},
|
||||
handler: async (ctx, args) => {
|
||||
const limit = args.limit ?? 50
|
||||
const limit = args.limit ?? 10
|
||||
|
||||
const events = await ctx.db
|
||||
let events = await ctx.db
|
||||
.query("usbPolicyEvents")
|
||||
.withIndex("by_machine_created", (q) => q.eq("machineId", args.machineId))
|
||||
.order("desc")
|
||||
.take(limit)
|
||||
.collect()
|
||||
|
||||
return events.map((event) => ({
|
||||
id: event._id,
|
||||
oldPolicy: event.oldPolicy,
|
||||
newPolicy: event.newPolicy,
|
||||
status: event.status,
|
||||
error: event.error,
|
||||
actorEmail: event.actorEmail,
|
||||
actorName: event.actorName,
|
||||
createdAt: event.createdAt,
|
||||
appliedAt: event.appliedAt,
|
||||
}))
|
||||
// Aplica filtro de cursor (paginacao)
|
||||
if (args.cursor !== undefined) {
|
||||
events = events.filter((e) => e.createdAt < args.cursor!)
|
||||
}
|
||||
|
||||
// Aplica filtro de status
|
||||
if (args.status) {
|
||||
events = events.filter((e) => e.status === args.status)
|
||||
}
|
||||
|
||||
// Aplica filtro de data
|
||||
if (args.dateFrom !== undefined) {
|
||||
events = events.filter((e) => e.createdAt >= args.dateFrom!)
|
||||
}
|
||||
if (args.dateTo !== undefined) {
|
||||
events = events.filter((e) => e.createdAt <= args.dateTo!)
|
||||
}
|
||||
|
||||
const hasMore = events.length > limit
|
||||
const results = events.slice(0, limit)
|
||||
const nextCursor = results.length > 0 ? results[results.length - 1].createdAt : undefined
|
||||
|
||||
return {
|
||||
events: results.map((event) => ({
|
||||
id: event._id,
|
||||
oldPolicy: event.oldPolicy,
|
||||
newPolicy: event.newPolicy,
|
||||
status: event.status,
|
||||
error: event.error,
|
||||
actorEmail: event.actorEmail,
|
||||
actorName: event.actorName,
|
||||
createdAt: event.createdAt,
|
||||
appliedAt: event.appliedAt,
|
||||
})),
|
||||
hasMore,
|
||||
nextCursor,
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue