Add multi-item Jira ticket creation from Ivanti Queue

Select multiple queue items and create a single consolidated Jira ticket
with aggregated summary and description. Adds multi-select mode with
checkboxes, floating action bar, consolidation modal, and junction table
to track which queue items contributed to each ticket.

- Migration: jira_ticket_queue_items junction table
- POST /api/jira-tickets/:id/queue-items endpoint
- GET /api/ivanti/todo-queue/ticket-links endpoint
- ConsolidationModal component with aggregation logic
- IvantiTodoQueuePage with selection mode and ticket link badges
- Pure utility functions for summary/description generation
- 34 tests passing (backend + frontend)
This commit is contained in:
Jordan Ramos
2026-05-22 11:12:45 -06:00
parent 704432788c
commit 6b805ee633
10 changed files with 2281 additions and 0 deletions

View File

@@ -396,6 +396,41 @@ function createIvantiTodoQueueRouter() {
}
});
/**
* GET /api/ivanti/todo-queue/ticket-links
*
* Returns Jira ticket associations for the current user's queue items.
* Joins jira_ticket_queue_items with jira_tickets to get ticket_key and url.
*
* @returns {Object} { links: { [queue_item_id]: { ticket_key, jira_url } } }
* @error 500 Internal server error
*/
router.get('/ticket-links', requireAuth(), async (req, res) => {
try {
const { rows } = await pool.query(
`SELECT jtqi.queue_item_id, jt.ticket_key, jt.url AS jira_url
FROM jira_ticket_queue_items jtqi
JOIN jira_tickets jt ON jt.id = jtqi.jira_ticket_id
JOIN ivanti_todo_queue q ON q.id = jtqi.queue_item_id
WHERE q.user_id = $1`,
[req.user.id]
);
const links = {};
for (const row of rows) {
links[row.queue_item_id] = {
ticket_key: row.ticket_key,
jira_url: row.jira_url
};
}
res.json({ links });
} catch (err) {
console.error('Error fetching ticket links:', err);
res.status(500).json({ error: 'Internal server error.' });
}
});
/**
* DELETE /api/ivanti/todo-queue/completed
*