import { Heading, Icon, Span, Stack, Text, Timeline} from '@chakra-ui/react'; import React, { Fragment, useMemo } from "react"; import { BsExclamationTriangle, BsSkipForward, BsStoplights } from "react-icons/bs"; import { MdMusicNote } from "react-icons/md"; import type {JsonPlayObject, LifecycleStep} from "../../core/Atomic"; import { patchObject } from "../../core/DataUtils"; import { timelineIconProps, timelineTextFormatting } from "../utils/ComponentUtils"; import { ChakraCodeBlockShort } from "./CodeBlock"; import { ErrorAlert } from "./ErrorAlert"; import { MSCollapsible, type MSCollapsibleExternalProps } from "./MSCollapsible"; import { PlayData } from "./PlayData"; import { Muted } from "./Typography"; import { JsonDiffPatch } from "./diffs/JsonDiff"; export interface LifeycleStepsTimelineProps extends MSCollapsibleExternalProps { steps: LifecycleStep[] original: JsonPlayObject } export const diffElements = (original: JsonPlayObject, steps: LifecycleStep[]): [React.JSX.Element[], JsonPlayObject?] => { const currentPlay: JsonPlayObject = structuredClone(original); // JSON.parse(JSON.stringify(original)); let patchFailed = false; const diffElements: React.JSX.Element[] | null = []; let index = 0; for (const step of steps) { index++; const { patch, error } = step; if (patch === undefined) { if (error !== undefined) { diffElements.push(null); } else { diffElements.push(Play was identical after Transform.); } continue; } if (patchFailed) { diffElements.push(); continue; } const left: JsonPlayObject = structuredClone(currentPlay); // JSON.parse(JSON.stringify(currentPlay)); left.data.meta = { ...(left.data.meta ?? {}), brainz: { ...(left.data.meta?.brainz ?? {}) } } currentPlay.data.meta = { ...(currentPlay.data.meta ?? {}), brainz: { ...(currentPlay.data.meta?.brainz ?? {}) } } try { currentPlay.data = patchObject(currentPlay.data, patch)// jdiff.patch(currentPlay, patch) as JsonPlayObject; diffElements.push( ) } catch (e) { diffElements.push(); patchFailed = true; } } return [diffElements, patchFailed !== undefined ? currentPlay : undefined] } export const TransformSteps = (props: LifeycleStepsTimelineProps) => { const { steps, original, collapsibleOpen } = props; const [diffs, finalPlay] = useMemo(() => diffElements(original, steps), [steps, original]); return ( {steps.map((x, index) => { const { patch, inputs, source, error, flowKnownState, flowReason, flowResult, stageName, stageType, hook } = x; let timelineIcon: React.JSX.Element, iconProps: Record, summary: React.JSX.Element, alertStatus: "error" | "info" | "warning" | "success" | "neutral"; if(error === undefined && error !== null) { timelineIcon = ; iconProps = flowResult === 'continue' ? {color: "green.focusRing"} : {color: "red.focusRing"}; summary = was completed{flowResult === 'stop' ? and stopped due to onSuccess condition : null}; if(patch === undefined) { summary = {summary} with no change to Play; } } else { if(flowKnownState === 'skip') { timelineIcon = ; summary = was skipped.; alertStatus = 'info'; } else if(flowKnownState === 'prereq') { timelineIcon = ; iconProps = {color: "orange.focusRing"}; summary = was not completed due to prerequisite failure.; alertStatus = "warning"; } else { if(flowResult === 'continue') { timelineIcon = ; iconProps = {color: "orange.focusRing"}; summary = encountered an error but will continue due to onFailure condition.; } else { timelineIcon = ; iconProps = {color: "red.focusRing"}; summary = encountered an error. } } } return {timelineIcon} Stage {stageType}-{stageName} in Hook {hook} from {source} {summary}} defaultOpen={collapsibleOpen} disableUntil="md" unmountOnExit timeline> {error !== undefined && error !== null ? : null} {diffs[index] !== null ? ( Diff {diffs[index]} ) : null} {inputs !== undefined && inputs.length > 0 ? ( Inputs {x.inputs.map((y, inputsIndex) => { return })} ) : null} })} {finalPlay !== undefined ? ( Final Playafter all Transforms ) : null} ) }