Saltar al contenido principal

Action Dialog

DyonaActionDialog captura los parámetros de una acción con un DyonaForm antes de que Action Engine la ejecute. Es la capa de captura de parámetros sobre Action Engine.

Flujo​

DyonaAction
requiresParameters: true
↓
DyonaActionDialog
↓
DyonaForm
↓
submit válido
↓
context.parameters
↓
executeDyonaAction()
↓
executor consumidor

Rechazar pedido con motivo​

Esta acción de record necesita un motivo de rechazo antes de poder ejecutarse.

const rejectAction: DyonaAction = {
id: 'reject-order',
label: 'Reject order',
scope: 'record',
requiresParameters: true,
};

const context: DyonaActionContext = {
sourceId: 'orders',
record: {
id: 1024,
customer: 'Acme Corp',
status: 'pending',
},
};

El formulario del diálogo solicita un select obligatorio rejectionReason y un textarea opcional comments. Luego de un submit válido, sus valores normalizados se asignan a context.parameters en el contexto de ejecución que recibe el executor.

DyonaActionDialogConfig​

  • schema: el DyonaFormSchema que se renderiza dentro del diálogo.
  • initialValues: valores opcionales de DyonaForm para precargar el formulario.
  • maxWidth: ancho opcional del diálogo: xs, sm, md, lg, xl o false.
  • fullWidth: permite que el diálogo use el ancho disponible hasta maxWidth.

Props principales​

  • open controla si el diálogo es visible.
  • action es la DyonaAction que se ejecutará.
  • context es el contexto de la acción; los valores del formulario se agregan como context.parameters en el contexto de ejecución.
  • config entrega el formulario y la configuración de layout del diálogo.
  • executor ejecuta la acción mediante Action Engine.
  • dataSourceExecutor resuelve datos del formulario cuando un field necesita datos de autocomplete remoto.
  • onClose cierra el diálogo en el componente consumidor.
  • onResult recibe un resultado de la acción.
  • onExecutionError recibe una excepción producida al ejecutar la acción.

executor y dataSourceExecutor tienen responsabilidades distintas: el primero ejecuta la acción de negocio; el segundo resuelve datos requeridos por el formulario, como opciones de autocomplete remoto.

Comportamiento​

  • El componente solo se renderiza cuando action.requiresParameters es true.
  • Un submit inválido no ejecuta la acción.
  • Un submit válido asigna valores normalizados del formulario a context.parameters en el contexto de ejecución.
  • Evita una segunda ejecución mientras haya una en curso.
  • Mientras ejecuta, Cancelar, Escape y el cierre por backdrop quedan bloqueados.
  • Un resultado con success: true se informa mediante onResult y cierra el diálogo.
  • Un resultado con success: false se informa mediante onResult y mantiene abierto el diálogo.
  • Una excepción del executor llama a onExecutionError y mantiene abierto el diálogo.

Ejemplo completo​

import {useState} from 'react';
import {
DyonaActionDialog,
type DyonaAction,
type DyonaActionContext,
type DyonaActionExecutor,
type DyonaActionResult,
} from '@typhonsoftware/dyona-form';

const rejectAction: DyonaAction = {
id: 'reject-order',
label: 'Rechazar pedido',
scope: 'record',
requiresParameters: true,
};

const context: DyonaActionContext = {
sourceId: 'orders',
record: {
id: 1024,
customer: 'Acme Corp',
status: 'pending',
},
};

const dialogConfig = {
schema: {
title: 'Rechazar pedido',
hideSingleTab: true,
tabs: [
{
id: 'rejection',
title: 'Detalle del rechazo',
rows: [
{
columns: [
{
name: 'rejectionReason',
label: 'Motivo del rechazo',
type: 'select' as const,
required: true,
options: [
{value: 'out-of-stock', label: 'Sin stock'},
{value: 'pricing-error', label: 'Error de precio'},
{value: 'customer-request', label: 'Solicitud del cliente'},
],
fullWidth: true,
},
],
},
{
columns: [
{
name: 'comments',
label: 'Comentarios',
type: 'textarea' as const,
fullWidth: true,
},
],
},
],
},
],
},
initialValues: {comments: ''},
maxWidth: 'sm' as const,
fullWidth: true,
};

const rejectOrder: DyonaActionExecutor = async ({context}) => {
const result: DyonaActionResult = {
success: true,
message: `Pedido ${context.record?.id} rechazado`,
data: {
rejectionReason: context.parameters?.rejectionReason,
comments: context.parameters?.comments,
},
refresh: [{sourceId: 'orders'}],
};

return result;
};

export function RejectOrderAction() {
const [open, setOpen] = useState(false);

return (
<>
<button onClick={() => setOpen(true)}>Rechazar pedido</button>

<DyonaActionDialog
locale="es"
open={open}
action={rejectAction}
context={context}
config={dialogConfig}
executor={rejectOrder}
onClose={() => setOpen(false)}
onResult={(result) => console.log(result.message)}
onExecutionError={(error) => console.error(error)}
/>
</>
);
}

Probar Action Dialog en el Lab