* feat: Add routing trace presenters Add domain-specific presenters (SalesforceRoutingTracePresenter, RoutingFormTracePresenter) that format trace steps into human-readable strings, and a core RoutingTracePresenter that delegates to them based on step domain. Includes unit tests for all presenters. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: Add findByBookingUid to RoutingTraceRepository Add method to look up a routing trace by booking UID, needed by the routing trace presenter tRPC endpoint. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: Add getRoutingTrace tRPC endpoint Expose routing trace data for a booking via viewer.bookings.getRoutingTrace. Tries the permanent RoutingTrace first (round robin bookings), then falls back to PendingRoutingTrace via the booking's form response relation. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: Add routing trace side sheet to booking list item Add a route icon button on booking list items that came from routing forms. Clicking it opens a side sheet displaying the full routing trace as human-readable steps. Adds RoutingTraceSheet component, store state, and translation key. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * refactor: Move routing trace action to dropdown menu Move the routing trace button from a standalone icon on the booking list item into the actions dropdown menu alongside "Report wrong assignment". The RoutingTraceSheet is now rendered from BookingActionsDropdown. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: Improve routing trace UI and handle unnamed routes - Redesign RoutingTraceSheet with vertical timeline layout, domain badges, skeleton loading state, and millisecond timestamps - Use Salesforce app-store icon for Salesforce steps - Fall back to "Unnamed route" when route name is missing or matches route ID - Fix dropdown menu icon to git-merge (valid icon, unique in menu) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: Add tests for getRoutingTrace handler and findByBookingUid repository method Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> * Abstract functions * Fix build error * Add permission check * fix: Update getRoutingTrace tests to include ctx and mock BookingAccessService Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
51 lines
1.5 KiB
TypeScript
51 lines
1.5 KiB
TypeScript
import { ROUTING_TRACE_DOMAINS } from "../constants";
|
|
import type { RoutingTraceService } from "../services/RoutingTraceService";
|
|
|
|
export const ROUTING_FORM_STEPS = {
|
|
ROUTE_MATCHED: "route_matched",
|
|
FALLBACK_ROUTE_USED: "fallback_route_used",
|
|
ATTRIBUTE_LOGIC_EVALUATED: "attribute-logic-evaluated",
|
|
ATTRIBUTE_FALLBACK_USED: "attribute_fallback_used",
|
|
} as const;
|
|
|
|
export class RoutingFormTraceService {
|
|
constructor(private readonly traceService: RoutingTraceService) {}
|
|
|
|
routeMatched(data: { routeId: string; routeName: string }): void {
|
|
this.traceService.addStep({
|
|
domain: ROUTING_TRACE_DOMAINS.ROUTING_FORM,
|
|
step: ROUTING_FORM_STEPS.ROUTE_MATCHED,
|
|
data,
|
|
});
|
|
}
|
|
|
|
fallbackRouteUsed(data: { routeId: string; routeName: string }): void {
|
|
this.traceService.addStep({
|
|
domain: ROUTING_TRACE_DOMAINS.ROUTING_FORM,
|
|
step: ROUTING_FORM_STEPS.FALLBACK_ROUTE_USED,
|
|
data,
|
|
});
|
|
}
|
|
|
|
attributeLogicEvaluated(data: {
|
|
routeName?: string;
|
|
routeIsFallback?: boolean;
|
|
checkedFallback?: boolean;
|
|
attributeRoutingDetails?: Array<{ attributeName: string; attributeValue: string }>;
|
|
}): void {
|
|
this.traceService.addStep({
|
|
domain: ROUTING_TRACE_DOMAINS.ROUTING_FORM,
|
|
step: ROUTING_FORM_STEPS.ATTRIBUTE_LOGIC_EVALUATED,
|
|
data,
|
|
});
|
|
}
|
|
|
|
attributeFallbackUsed(data: { routeName?: string }): void {
|
|
this.traceService.addStep({
|
|
domain: ROUTING_TRACE_DOMAINS.ROUTING_FORM,
|
|
step: ROUTING_FORM_STEPS.ATTRIBUTE_FALLBACK_USED,
|
|
data,
|
|
});
|
|
}
|
|
}
|