ui-nyla/src/api/automationApi.ts
2026-02-09 23:45:05 +01:00

376 lines
9.8 KiB
TypeScript

import { ApiRequestOptions } from '../hooks/useApi';
// ============================================================================
// TYPES & INTERFACES
// ============================================================================
export interface Automation {
id: string;
mandateId: string;
featureInstanceId: string;
label: string;
template: string | object;
placeholders: Record<string, string>;
schedule: string;
active: boolean;
status?: string;
lastExecution?: number;
nextExecution?: number;
executionLogs?: AutomationLog[];
allowedProviders?: string[];
_createdAt?: number;
_updatedAt?: number;
_createdByUserName?: string;
mandateName?: string;
featureInstanceName?: string;
[key: string]: any;
}
export interface AutomationLog {
id: string;
timestamp: number;
status: string;
workflowId?: string;
messages?: string[];
}
// Multilingual text type (matches backend TextMultilingual)
export interface TextMultilingual {
en: string;
ge?: string;
fr?: string;
it?: string;
}
// AutomationTemplate from DB
export interface AutomationTemplate {
id: string;
label: TextMultilingual;
overview?: TextMultilingual;
template: string; // JSON string with {{KEY:...}} placeholders
_createdAt?: number;
_createdBy?: string;
_createdByUserName?: string;
}
// Workflow action definition from backend
export interface WorkflowAction {
method: string;
action: string;
actionId: string;
description: string;
category?: string;
parameters: WorkflowActionParameter[];
exampleJson: {
execMethod: string;
execAction: string;
execParameters: Record<string, any>;
execResultLabel: string;
};
}
export interface WorkflowActionParameter {
name: string;
type: string;
frontendType: string;
required: boolean;
default?: any;
description: string;
frontendOptions?: string | string[];
}
export interface CreateAutomationRequest {
label: string;
template: string;
placeholders?: Record<string, string>;
schedule?: string;
active?: boolean;
mandateId?: string;
featureInstanceId?: string;
}
export interface UpdateAutomationRequest {
label?: string;
template?: string;
placeholders?: Record<string, string>;
schedule?: string;
active?: boolean;
}
export interface ExecuteAutomationResponse {
id: string;
status: string;
workflowId?: string;
[key: string]: any;
}
// Type for the request function passed to API functions
export type ApiRequestFunction = (options: ApiRequestOptions<any>) => Promise<any>;
// ============================================================================
// API REQUEST FUNCTIONS
// ============================================================================
/**
* Fetch all automations for the current mandate
* Endpoint: GET /api/automations
*/
export async function fetchAutomations(request: ApiRequestFunction): Promise<Automation[]> {
console.log('📤 fetchAutomations: Making API request to /api/automations');
try {
const data = await request({
url: '/api/automations',
method: 'get'
});
console.log('📥 fetchAutomations: API response:', data);
// Handle different response formats
let automations: Automation[] = [];
if (Array.isArray(data)) {
automations = data;
} else if (data && typeof data === 'object') {
if (Array.isArray(data.automations)) {
automations = data.automations;
} else if (Array.isArray(data.items)) {
automations = data.items;
} else if (Array.isArray(data.data)) {
automations = data.data;
}
}
console.log(`✅ fetchAutomations: Returning ${automations.length} automations`);
return automations;
} catch (error) {
console.error('❌ fetchAutomations: Error fetching automations:', error);
throw error;
}
}
/**
* Fetch a single automation by ID
* Endpoint: GET /api/automations/{automationId}
*/
export async function fetchAutomation(
request: ApiRequestFunction,
automationId: string
): Promise<Automation> {
return await request({
url: `/api/automations/${automationId}`,
method: 'get'
});
}
/**
* Create a new automation
* Endpoint: POST /api/automations
*/
export async function createAutomationApi(
request: ApiRequestFunction,
automationData: CreateAutomationRequest
): Promise<Automation> {
return await request({
url: '/api/automations',
method: 'post',
data: automationData
});
}
/**
* Update an existing automation
* Endpoint: PUT /api/automations/{automationId}
*/
export async function updateAutomationApi(
request: ApiRequestFunction,
automationId: string,
updateData: UpdateAutomationRequest
): Promise<Automation> {
return await request({
url: `/api/automations/${automationId}`,
method: 'put',
data: updateData
});
}
/**
* Delete an automation
* Endpoint: DELETE /api/automations/{automationId}
*/
export async function deleteAutomationApi(
request: ApiRequestFunction,
automationId: string
): Promise<void> {
await request({
url: `/api/automations/${automationId}`,
method: 'delete'
});
}
/**
* Execute an automation (test mode)
* Endpoint: POST /api/automations/{automationId}/execute
*/
export async function executeAutomationApi(
request: ApiRequestFunction,
automationId: string
): Promise<ExecuteAutomationResponse> {
return await request({
url: `/api/automations/${automationId}/execute`,
method: 'post'
});
}
/**
* Fetch automation attributes for dynamic form generation
* Endpoint: GET /api/attributes/AutomationDefinition
*/
export async function fetchAutomationAttributes(
request: ApiRequestFunction
): Promise<any[]> {
const data = await request({
url: '/api/attributes/AutomationDefinition',
method: 'get'
});
if (data?.attributes && Array.isArray(data.attributes)) {
return data.attributes;
}
if (Array.isArray(data)) {
return data;
}
return [];
}
// ============================================================================
// AUTOMATION TEMPLATES API
// ============================================================================
/**
* Fetch all automation templates (RBAC-filtered: own templates)
* Endpoint: GET /api/automation-templates
*/
export async function fetchAutomationTemplates(
request: ApiRequestFunction
): Promise<AutomationTemplate[]> {
const data = await request({
url: '/api/automation-templates',
method: 'get'
});
if (data?.items && Array.isArray(data.items)) {
return data.items;
}
return Array.isArray(data) ? data : [];
}
/**
* Fetch single automation template by ID
* Endpoint: GET /api/automation-templates/{templateId}
*/
export async function fetchAutomationTemplateById(
request: ApiRequestFunction,
templateId: string
): Promise<AutomationTemplate | null> {
try {
return await request({
url: `/api/automation-templates/${templateId}`,
method: 'get'
});
} catch (error) {
console.error('Error fetching template:', error);
return null;
}
}
/**
* Create new automation template
* Endpoint: POST /api/automation-templates
*/
export async function createAutomationTemplateApi(
request: ApiRequestFunction,
templateData: Omit<AutomationTemplate, 'id' | '_createdAt' | '_createdBy'>
): Promise<AutomationTemplate> {
return await request({
url: '/api/automation-templates',
method: 'post',
data: templateData
});
}
/**
* Update automation template
* Endpoint: PUT /api/automation-templates/{templateId}
*/
export async function updateAutomationTemplateApi(
request: ApiRequestFunction,
templateId: string,
templateData: Partial<AutomationTemplate>
): Promise<AutomationTemplate> {
return await request({
url: `/api/automation-templates/${templateId}`,
method: 'put',
data: templateData
});
}
/**
* Delete automation template
* Endpoint: DELETE /api/automation-templates/{templateId}
*/
export async function deleteAutomationTemplateApi(
request: ApiRequestFunction,
templateId: string
): Promise<void> {
await request({
url: `/api/automation-templates/${templateId}`,
method: 'delete'
});
}
/**
* Fetch automation template attributes for dynamic form generation
* Endpoint: GET /api/automation-templates/attributes
*/
export async function fetchAutomationTemplateAttributes(
request: ApiRequestFunction
): Promise<any[]> {
const data = await request({
url: '/api/automation-templates/attributes',
method: 'get'
});
// Backend returns: { attributes: { model: "...", attributes: [...] } }
if (data?.attributes?.attributes && Array.isArray(data.attributes.attributes)) {
return data.attributes.attributes;
}
// Fallback: direct attributes array
if (data?.attributes && Array.isArray(data.attributes)) {
return data.attributes;
}
return Array.isArray(data) ? data : [];
}
// ============================================================================
// WORKFLOW ACTIONS API
// ============================================================================
/**
* Fetch available workflow actions (RBAC-filtered)
* Endpoint: GET /api/automations/actions
*/
export async function fetchWorkflowActions(
request: ApiRequestFunction
): Promise<WorkflowAction[]> {
const data = await request({
url: '/api/automations/actions',
method: 'get'
});
return data?.actions || [];
}