| 1 | import type { FlaskBaseResponse } from "@/types/flask.d" |
| 2 | import type { |
| 3 | NotificationDispatchLogEntry, |
| 4 | NotificationRoute, |
| 5 | NotificationRoutePayload, |
| 6 | NotificationRouteUpdatePayload, |
| 7 | ShuffleApp, |
| 8 | ShuffleIntegration, |
| 9 | ShuffleIntegrationPayload, |
| 10 | ShuffleIntegrationUpdatePayload, |
| 11 | ShuffleOrg, |
| 12 | ShuffleVerifyResult |
| 13 | } from "@/types/notifications.d" |
| 14 | import { HttpClient } from "../httpClient" |
| 15 | |
| 16 | // Per-customer notification routing — wraps app/notifications/routes/notifications.py. |
| 17 | // Used by the Customer detail page's "AI Notifications" tab to manage who |
| 18 | // receives notifications about Talon's investigation results. |
| 19 | |
| 20 | export default { |
| 21 | listRoutes(customerCode: string) { |
| 22 | return HttpClient.get<FlaskBaseResponse & { routes: NotificationRoute[] }>( |
| 23 | `/customers/${customerCode}/notification_routes` |
| 24 | ) |
| 25 | }, |
| 26 | |
| 27 | createRoute(customerCode: string, payload: NotificationRoutePayload) { |
| 28 | return HttpClient.post<FlaskBaseResponse & { route: NotificationRoute }>( |
| 29 | `/customers/${customerCode}/notification_routes`, |
| 30 | payload |
| 31 | ) |
| 32 | }, |
| 33 | |
| 34 | updateRoute(customerCode: string, routeId: number, payload: NotificationRouteUpdatePayload) { |
| 35 | return HttpClient.patch<FlaskBaseResponse & { route: NotificationRoute }>( |
| 36 | `/customers/${customerCode}/notification_routes/${routeId}`, |
| 37 | payload |
| 38 | ) |
| 39 | }, |
| 40 | |
| 41 | deleteRoute(customerCode: string, routeId: number) { |
| 42 | return HttpClient.delete<FlaskBaseResponse>(`/customers/${customerCode}/notification_routes/${routeId}`) |
| 43 | }, |
| 44 | |
| 45 | listDispatchLog(customerCode: string) { |
| 46 | return HttpClient.get<FlaskBaseResponse & { entries: NotificationDispatchLogEntry[] }>( |
| 47 | `/customers/${customerCode}/notification_dispatch_log` |
| 48 | ) |
| 49 | }, |
| 50 | |
| 51 | // ----- Shuffle integrations (Phase 2) ----- |
| 52 | |
| 53 | listShuffleIntegrations(customerCode: string) { |
| 54 | return HttpClient.get<FlaskBaseResponse & { integrations: ShuffleIntegration[] }>( |
| 55 | `/customers/${customerCode}/shuffle_integrations` |
| 56 | ) |
| 57 | }, |
| 58 | |
| 59 | createShuffleIntegration(customerCode: string, payload: ShuffleIntegrationPayload) { |
| 60 | return HttpClient.post<FlaskBaseResponse & { integration: ShuffleIntegration }>( |
| 61 | `/customers/${customerCode}/shuffle_integrations`, |
| 62 | payload |
| 63 | ) |
| 64 | }, |
| 65 | |
| 66 | updateShuffleIntegration(customerCode: string, integrationId: number, payload: ShuffleIntegrationUpdatePayload) { |
| 67 | return HttpClient.patch<FlaskBaseResponse & { integration: ShuffleIntegration }>( |
| 68 | `/customers/${customerCode}/shuffle_integrations/${integrationId}`, |
| 69 | payload |
| 70 | ) |
| 71 | }, |
| 72 | |
| 73 | deleteShuffleIntegration(customerCode: string, integrationId: number) { |
| 74 | return HttpClient.delete<FlaskBaseResponse>(`/customers/${customerCode}/shuffle_integrations/${integrationId}`) |
| 75 | }, |
| 76 | |
| 77 | listShuffleApps(customerCode: string, integrationId: number) { |
| 78 | return HttpClient.get<FlaskBaseResponse & { apps: ShuffleApp[] }>( |
| 79 | `/customers/${customerCode}/shuffle_integrations/${integrationId}/apps` |
| 80 | ) |
| 81 | }, |
| 82 | |
| 83 | verifyShuffleIntegration(customerCode: string, integrationId: number) { |
| 84 | return HttpClient.get<FlaskBaseResponse & ShuffleVerifyResult>( |
| 85 | `/customers/${customerCode}/shuffle_integrations/${integrationId}/verify` |
| 86 | ) |
| 87 | }, |
| 88 | |
| 89 | // Phase 3a — deployment-scoped org listing for the integration form's |
| 90 | // dropdown picker. Not customer-scoped; the admin Bearer (Shuffle |
| 91 | // connector) has access to every org we can attach. |
| 92 | listShuffleOrgs() { |
| 93 | return HttpClient.get<FlaskBaseResponse & { orgs: ShuffleOrg[] }>(`/notifications/shuffle/orgs`) |
| 94 | } |
| 95 | } |