New alert service
This commit is contained in:
178
frontend/src/utils/eventI18n.ts
Normal file
178
frontend/src/utils/eventI18n.ts
Normal file
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* Clean i18n Parameter System for Event Content in Frontend
|
||||
*
|
||||
* Handles rendering of parameterized content for:
|
||||
* - Alert titles and messages
|
||||
* - Notification titles and messages
|
||||
* - Recommendation titles and messages
|
||||
* - AI reasoning summaries
|
||||
* - Action labels and consequences
|
||||
*/
|
||||
|
||||
import { I18nContent, Event, Alert, Notification, Recommendation, SmartAction } from '../api/types/events';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface I18nRenderer {
|
||||
renderTitle: (titleKey: string, titleParams?: Record<string, any>) => string;
|
||||
renderMessage: (messageKey: string, messageParams?: Record<string, any>) => string;
|
||||
renderReasoningSummary: (summaryKey: string, summaryParams?: Record<string, any>) => string;
|
||||
renderActionLabel: (labelKey: string, labelParams?: Record<string, any>) => string;
|
||||
renderUrgencyReason: (reasonKey: string, reasonParams?: Record<string, any>) => string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a parameterized template with given parameters
|
||||
*/
|
||||
export const renderTemplate = (template: string, params: Record<string, any> = {}): string => {
|
||||
if (!template) return '';
|
||||
|
||||
let result = template;
|
||||
for (const [key, value] of Object.entries(params)) {
|
||||
// Replace {{key}} with the value, handling nested properties
|
||||
const regex = new RegExp(`{{\\s*${key}\\s*}}`, 'g');
|
||||
result = result.replace(regex, String(value ?? ''));
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook for accessing the i18n renderer within React components
|
||||
*/
|
||||
export const useEventI18n = (): I18nRenderer => {
|
||||
const { t } = useTranslation(['events', 'common']);
|
||||
|
||||
const renderTitle = (titleKey: string, titleParams: Record<string, any> = {}): string => {
|
||||
return t(titleKey, { defaultValue: titleKey, ...titleParams });
|
||||
};
|
||||
|
||||
const renderMessage = (messageKey: string, messageParams: Record<string, any> = {}): string => {
|
||||
return t(messageKey, { defaultValue: messageKey, ...messageParams });
|
||||
};
|
||||
|
||||
const renderReasoningSummary = (summaryKey: string, summaryParams: Record<string, any> = {}): string => {
|
||||
return t(summaryKey, { defaultValue: summaryKey, ...summaryParams });
|
||||
};
|
||||
|
||||
const renderActionLabel = (labelKey: string, labelParams: Record<string, any> = {}): string => {
|
||||
return t(labelKey, { defaultValue: labelKey, ...labelParams });
|
||||
};
|
||||
|
||||
const renderUrgencyReason = (reasonKey: string, reasonParams: Record<string, any> = {}): string => {
|
||||
return t(reasonKey, { defaultValue: reasonKey, ...reasonParams });
|
||||
};
|
||||
|
||||
return {
|
||||
renderTitle,
|
||||
renderMessage,
|
||||
renderReasoningSummary,
|
||||
renderActionLabel,
|
||||
renderUrgencyReason
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Render i18n content for an event
|
||||
*/
|
||||
export const renderEventContent = (i18n: I18nContent, language?: string): { title: string; message: string } => {
|
||||
const title = renderTemplate(i18n.title_key, i18n.title_params);
|
||||
const message = renderTemplate(i18n.message_key, i18n.message_params);
|
||||
|
||||
return { title, message };
|
||||
};
|
||||
|
||||
/**
|
||||
* Render all content for an alert
|
||||
*/
|
||||
export const renderAlertContent = (alert: Alert, language?: string) => {
|
||||
const { title, message } = renderEventContent(alert.i18n, language);
|
||||
|
||||
let reasoningSummary = '';
|
||||
if (alert.ai_reasoning?.summary_key) {
|
||||
reasoningSummary = renderTemplate(
|
||||
alert.ai_reasoning.summary_key,
|
||||
alert.ai_reasoning.summary_params
|
||||
);
|
||||
}
|
||||
|
||||
// Render smart actions with parameterized labels
|
||||
const renderedActions = alert.smart_actions.map(action => ({
|
||||
...action,
|
||||
label: renderTemplate(action.label_key, action.label_params),
|
||||
consequence: action.consequence_key
|
||||
? renderTemplate(action.consequence_key, action.consequence_params)
|
||||
: undefined,
|
||||
disabled_reason: action.disabled_reason_key
|
||||
? renderTemplate(action.disabled_reason_key, action.disabled_reason_params)
|
||||
: action.disabled_reason
|
||||
}));
|
||||
|
||||
return {
|
||||
title,
|
||||
message,
|
||||
reasoningSummary,
|
||||
renderedActions
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Render all content for a notification
|
||||
*/
|
||||
export const renderNotificationContent = (notification: Notification, language?: string) => {
|
||||
const { title, message } = renderEventContent(notification.i18n, language);
|
||||
|
||||
return {
|
||||
title,
|
||||
message
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Render all content for a recommendation
|
||||
*/
|
||||
export const renderRecommendationContent = (recommendation: Recommendation, language?: string) => {
|
||||
const { title, message } = renderEventContent(recommendation.i18n, language);
|
||||
|
||||
let reasoningSummary = '';
|
||||
if (recommendation.ai_reasoning?.summary_key) {
|
||||
reasoningSummary = renderTemplate(
|
||||
recommendation.ai_reasoning.summary_key,
|
||||
recommendation.ai_reasoning.summary_params
|
||||
);
|
||||
}
|
||||
|
||||
// Render suggested actions with parameterized labels
|
||||
const renderedSuggestedActions = recommendation.suggested_actions.map(action => ({
|
||||
...action,
|
||||
label: renderTemplate(action.label_key, action.label_params),
|
||||
consequence: action.consequence_key
|
||||
? renderTemplate(action.consequence_key, action.consequence_params)
|
||||
: undefined,
|
||||
disabled_reason: action.disabled_reason_key
|
||||
? renderTemplate(action.disabled_reason_key, action.disabled_reason_params)
|
||||
: action.disabled_reason
|
||||
}));
|
||||
|
||||
return {
|
||||
title,
|
||||
message,
|
||||
reasoningSummary,
|
||||
renderedSuggestedActions
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Render content for any event type
|
||||
*/
|
||||
export const renderEvent = (event: Event, language?: string) => {
|
||||
switch (event.event_class) {
|
||||
case 'alert':
|
||||
return renderAlertContent(event as Alert, language);
|
||||
case 'notification':
|
||||
return renderNotificationContent(event as Notification, language);
|
||||
case 'recommendation':
|
||||
return renderRecommendationContent(event as Recommendation, language);
|
||||
default:
|
||||
throw new Error(`Unknown event class: ${(event as any).event_class}`);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user