Create Element
Element to JSON
Learn how to convert the element into JSON so it can be stored in your backend.
Element to JSON
Since every element must have a JSON representation, we also need to define one for our new element. To do that, we'll update the following file:
// src/shared/kits/workflow/types/workflow-schema.ts
export type WorkflowSchema = {
start: { message: string };
elements: ElementSchema[];
end: { message: string };
};
export type ElementSchema =
| ActionSchema
| ConditionSchema
| SwitchSchema
| LoopSchema
| ParallelSchema;
export interface ActionSchema {
type: "action";
id: string;
message: string;
}
export interface ConditionSchema {
type: "condition";
id: string;
if: string;
then: ElementSchema[];
else: ElementSchema[];
}
export interface SwitchSchema {
type: "switch";
id: string;
branches: {
case: string;
then: ElementSchema[];
}[];
default: ElementSchema[];
}
export interface LoopSchema {
type: "loop";
id: string;
while: string;
into: ElementSchema[];
}
export interface ParallelSchema {
type: "parallel";
id: string;
branches: {
label: string;
then: ElementSchema[];
}[];
}
We'll also update the following file to export the type we created:
// src/shared/kits/workflow/index.tsx
export { useWorkflow, type State, type Action } from "./hooks/use-workflow";
export { WorkflowView } from "./components/workflow-view";
export { toWorkflowSchema } from "./utilities/to-workflow-schema";
export { toWorkflow } from "./utilities/to-workflow";
export type {
WorkflowSchema,
ElementSchema,
ActionSchema,
ConditionSchema,
SwitchSchema,
LoopSchema,
ParallelSchema,
} from "./types/workflow-schema";
export type {
Workflow,
ElementFlow,
ActionFlow,
ConditionFlow,
SwitchFlow,
LoopFlow,
ParallelFlow,
} from "./mvc/model/workflow";
export type { WorkflowChange } from "./mvc/model/workflow-change";
We'll also need to update the following function to map the new element to its JSON format:
// src/shared/kits/workflow/utilities/to-workflow-schema.ts
import type {
Workflow,
ElementFlow,
ActionFlow,
ConditionFlow,
SwitchFlow,
LoopFlow,
ParallelFlow,
} from "@/shared/kits/workflow";
import type {
WorkflowSchema,
ElementSchema,
ActionSchema,
ConditionSchema,
SwitchSchema,
LoopSchema,
ParallelSchema,
} from "../types/workflow-schema";
export function toWorkflowSchema(workflow: Workflow): WorkflowSchema {
return {
start: { message: workflow.flow.start.message },
elements: workflow.flow.elements.map((element) => elementToSchema(element)),
end: { message: workflow.flow.end.message },
};
}
export function elementToSchema(elementFlow: ElementFlow): ElementSchema {
switch (elementFlow.type) {
case "action":
return actionToSchema(elementFlow);
case "condition":
return conditionToSchema(elementFlow);
case "switch":
return switchToSchema(elementFlow);
case "loop":
return loopToSchema(elementFlow);
case "parallel":
return parallelToSchema(elementFlow);
}
}
function actionToSchema(actionFlow: ActionFlow): ActionSchema {
return {
type: "action",
id: actionFlow.id,
message: actionFlow.message,
};
}
function conditionToSchema(conditionFlow: ConditionFlow): ConditionSchema {
return {
type: "condition",
id: conditionFlow.id,
if: conditionFlow.if,
then: conditionFlow.then.map(elementToSchema),
else: conditionFlow.else.map(elementToSchema),
};
}
function switchToSchema(switchFlow: SwitchFlow): SwitchSchema {
return {
type: "switch",
id: switchFlow.id,
branches: switchFlow.branches.map((branch) => ({
case: branch.case,
then: branch.then.map(elementToSchema),
})),
default: switchFlow.default.map(elementToSchema),
};
}
function loopToSchema(loopFlow: LoopFlow): LoopSchema {
return {
type: "loop",
id: loopFlow.id,
while: loopFlow.while,
into: loopFlow.into.map(elementToSchema),
};
}
function parallelToSchema(parallelFlow: ParallelFlow): ParallelSchema {
return {
type: "parallel",
id: parallelFlow.id,
branches: parallelFlow.branches.map((branch) => ({
label: branch.label,
then: branch.then.map(elementToSchema),
})),
};
}
We'll also need to update the following function to map the JSON format to the new element:
// src/shared/kits/workflow/utilities/to-workflow.ts
import type {
Workflow,
ElementFlow,
ActionFlow,
ConditionFlow,
SwitchFlow,
LoopFlow,
ParallelFlow,
} from "@/shared/kits/workflow";
import type {
WorkflowSchema,
ElementSchema,
ActionSchema,
ConditionSchema,
SwitchSchema,
LoopSchema,
ParallelSchema,
} from "../types/workflow-schema";
export function toWorkflow(schema: WorkflowSchema): Workflow {
return {
flow: {
start: { message: schema.start.message },
dropTop: new Set<string>(),
elements: schema.elements.map((element) => elementToWorkflow(element)),
end: { message: schema.end.message },
},
widget: null,
active: null,
failure: null,
};
}
export function elementToWorkflow(elementSchema: ElementSchema): ElementFlow {
switch (elementSchema.type) {
case "action":
return actionToWorkflow(elementSchema);
case "condition":
return conditionToWorkflow(elementSchema);
case "switch":
return switchToWorkflow(elementSchema);
case "loop":
return loopToWorkflow(elementSchema);
case "parallel":
return parallelToWorkflow(elementSchema);
}
}
function actionToWorkflow(actionSchema: ActionSchema): ActionFlow {
return {
type: "action",
id: actionSchema.id,
message: actionSchema.message,
dragging: null,
dropNext: new Set<string>(),
};
}
function conditionToWorkflow(conditionSchema: ConditionSchema): ConditionFlow {
return {
type: "condition",
id: conditionSchema.id,
if: conditionSchema.if,
then: conditionSchema.then.map(elementToWorkflow),
else: conditionSchema.else.map(elementToWorkflow),
dragging: null,
dropNext: new Set<string>(),
dropThen: new Set<string>(),
dropElse: new Set<string>(),
};
}
function switchToWorkflow(switchSchema: SwitchSchema): SwitchFlow {
return {
type: "switch",
id: switchSchema.id,
branches: switchSchema.branches.map((branch) => ({
case: branch.case,
then: branch.then.map(elementToWorkflow),
})),
default: switchSchema.default.map(elementToWorkflow),
dragging: null,
dropNext: new Set<string>(),
dropBranches: switchSchema.branches.map(() => new Set<string>()),
dropDefault: new Set<string>(),
};
}
function loopToWorkflow(loopSchema: LoopSchema): LoopFlow {
return {
type: "loop",
id: loopSchema.id,
while: loopSchema.while,
into: loopSchema.into.map(elementToWorkflow),
dragging: null,
dropNext: new Set<string>(),
dropInto: new Set<string>(),
};
}
function parallelToWorkflow(parallelSchema: ParallelSchema): ParallelFlow {
return {
type: "parallel",
id: parallelSchema.id,
branches: parallelSchema.branches.map((branch) => ({
label: branch.label,
then: branch.then.map(elementToWorkflow),
})),
dragging: null,
dropNext: new Set<string>(),
dropBranches: parallelSchema.branches.map(() => new Set<string>()),
};
}