Skip to content

Commit

Permalink
Add batching information to visualize (UI PR 3) (#499)
Browse files Browse the repository at this point in the history
Display batch information in visualize report:

* add batch style and logic to execution-batches section
* add batch style and logic to deployment flow section
* highlight module names in common

Adds a batches command to core to allow the visualization to display
batch information for a clean deployment.

This API is likely to change as it is tooling focused.
  • Loading branch information
zoeyTM authored and kanej committed Oct 4, 2023
1 parent 57e1021 commit 6e2ea28
Show file tree
Hide file tree
Showing 12 changed files with 245 additions and 59 deletions.
21 changes: 21 additions & 0 deletions packages/core/src/batches.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Batcher } from "./internal/batcher";
import { deploymentStateReducer } from "./internal/execution/reducers/deployment-state-reducer";
import { IgnitionModule, IgnitionModuleResult } from "./types/module";

/**
* Provides a array of batches, where each batch is an array of futureIds,
* based on Ignition's batching algorithm, assuming a the module is being
* run from as a fresh deployment.
*
* @param ignitionModule - the Ignition module to be get batch information for
* @returns the batches Ignition will use for the module
*
* @beta
*/
export function batches(
ignitionModule: IgnitionModule<string, string, IgnitionModuleResult<string>>
): string[][] {
const deploymentState = deploymentStateReducer(undefined);

return Batcher.batch(ignitionModule, deploymentState);
}
1 change: 1 addition & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { batches } from "./batches";
export { buildModule } from "./build-module";
export { deploy } from "./deploy";
export * from "./errors";
Expand Down
7 changes: 4 additions & 3 deletions packages/hardhat-plugin/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { DeploymentParameters } from "@nomicfoundation/ignition-core";

import "@nomicfoundation/hardhat-ethers";
import { batches, DeploymentParameters } from "@nomicfoundation/ignition-core";
import { existsSync, readdirSync, readJSONSync } from "fs-extra";
import { extendConfig, extendEnvironment, task } from "hardhat/config";
import { lazyObject } from "hardhat/plugins";
Expand Down Expand Up @@ -205,8 +204,10 @@ task("visualize")
const serializedIgnitionModule =
IgnitionModuleSerializer.serialize(userModule);

const batchInfo = batches(userModule);

await writeVisualization(
{ module: serializedIgnitionModule },
{ module: serializedIgnitionModule, batches: batchInfo },
{
cacheDir: hre.config.paths.cache,
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { ensureDir, pathExists, readFile, writeFile } from "fs-extra";
import path from "path";

export async function writeVisualization(
visualizationPayload: { module: SerializedIgnitionModule },
visualizationPayload: {
module: SerializedIgnitionModule;
batches: string[][];
},
{ cacheDir }: { cacheDir: string }
) {
const templateDir = path.join(
Expand Down
13 changes: 11 additions & 2 deletions packages/ui/scripts/generate-example-deployment-json.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { IgnitionModuleSerializer } from "@nomicfoundation/ignition-core";
import {
IgnitionModuleSerializer,
batches,
} from "@nomicfoundation/ignition-core";
import { writeFile } from "node:fs/promises";

import complexModule from "../examples/ComplexModule.js";
Expand All @@ -11,11 +14,17 @@ async function writeDeploymentJsonFor(ignitionModule) {
const serializedIgnitionModule =
IgnitionModuleSerializer.serialize(ignitionModule);

const moduleBatches = batches(ignitionModule);

console.log("Deployment written to ./public/deployment.json");

await writeFile(
"./public/deployment.json",
JSON.stringify({ module: serializedIgnitionModule }, undefined, 2)
JSON.stringify(
{ module: serializedIgnitionModule, batches: moduleBatches },
undefined,
2
)
);
}

Expand Down
34 changes: 24 additions & 10 deletions packages/ui/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@ import { VisualizationOverview } from "./pages/visualization-overview/visualizat

import "./main.css";

const loadDeploymentFromEmbeddedDiv = (): IgnitionModule<
string,
string,
IgnitionModuleResult<string>
> | null => {
const loadDeploymentFromEmbeddedDiv = (): {
ignitionModule: IgnitionModule<string, string, IgnitionModuleResult<string>>;
batches: string[][];
} | null => {
const scriptTag = document.getElementById("deployment");

if (scriptTag === null || scriptTag.textContent === null) {
Expand All @@ -30,13 +29,23 @@ const loadDeploymentFromEmbeddedDiv = (): IgnitionModule<
return null;
}

return IgnitionModuleDeserializer.deserialize(data.module);
return {
ignitionModule: IgnitionModuleDeserializer.deserialize(data.module),
batches: data.batches,
};
};

const loadDeploymentFromDevFile = async () => {
const loadDeploymentFromDevFile = async (): Promise<{
ignitionModule: IgnitionModule<string, string, IgnitionModuleResult<string>>;
batches: string[][];
}> => {
const response = await fetch("./deployment.json");
const data = await response.json();
return IgnitionModuleDeserializer.deserialize(data.module);

return {
ignitionModule: IgnitionModuleDeserializer.deserialize(data.module),
batches: data.batches,
};
};

const loadDeploymentData = () => {
Expand All @@ -45,12 +54,17 @@ const loadDeploymentData = () => {

const main = async () => {
try {
const ignitionModule = await loadDeploymentData();
const { ignitionModule, batches } = await loadDeploymentData();

const router = createHashRouter([
{
path: "/",
element: <VisualizationOverview ignitionModule={ignitionModule} />,
element: (
<VisualizationOverview
ignitionModule={ignitionModule}
batches={batches}
/>
),
},
]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,53 @@ import {
IgnitionModule,
IgnitionModuleResult,
} from "@nomicfoundation/ignition-core/ui-helpers";
import React from "react";
import React, { useState } from "react";
import { Tooltip } from "react-tooltip";
import styled from "styled-components";
import styled, { css } from "styled-components";
import { Mermaid } from "../../../components/mermaid";
import { toEscapedId } from "../../../utils/to-escaped-id";

export const DeploymentFlow: React.FC<{
ignitionModule: IgnitionModule<string, string, IgnitionModuleResult<string>>;
}> = ({ ignitionModule }) => {
batches: string[][];
}> = ({ ignitionModule, batches }) => {
const escapedIdMap = batches.reduce((acc, batch, i) => {
const batchId = `batch-${i}`;

const escapedFutureIds = batch.map(toEscapedId);

return {
...acc,
[batchId]: escapedFutureIds,
};
}, {} as Record<string, string[]>);

const [currentlyHovered, setCurrentlyHovered] = useState("");

const futuresToHighlight = escapedIdMap[currentlyHovered] || [];

return (
<div>
<SectionHeader>
Deployment flow <FlowTooltip />
</SectionHeader>

<Mermaid ignitionModule={ignitionModule} />
<BatchBtnSection>
Visualize batches:{" "}
{batches.map((_, i) => (
<BatchBtn
key={`batch-btn-${i}`}
onMouseEnter={() => setCurrentlyHovered(`batch-${i}`)}
onMouseLeave={() => setCurrentlyHovered("")}
>
Batch <strong>#{i + 1}</strong>
</BatchBtn>
))}
</BatchBtnSection>

<HighlightedFutures futures={futuresToHighlight}>
<Mermaid ignitionModule={ignitionModule} />
</HighlightedFutures>
</div>
);
};
Expand All @@ -37,8 +69,33 @@ const FlowTooltip: React.FC = () => (
</span>
);

const HighlightedFutures = styled.div<{ futures: string[] }>`
${({ futures }) =>
futures.map(
(id) =>
css`
g[id^="flowchart-${id}"] rect {
fill: lightgreen !important;
}
`
)}
`;

const SectionHeader = styled.div`
font-size: 1.5rem;
margin-bottom: 1rem;
margin-top: 1rem;
`;

const BatchBtnSection = styled.div`
margin-bottom: 1rem;
`;

const BatchBtn = styled.span`
font-size: 0.8rem;
background: #f2efef;
width: 86px;
text-align: center;
padding: 0.3rem 1rem;
margin: auto 0.5rem;
`;
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
Future,
FutureType,
IgnitionModule,
IgnitionModuleResult,
Expand All @@ -8,11 +9,12 @@ import { Tooltip } from "react-tooltip";
import styled from "styled-components";

import { getAllFuturesForModule } from "../../../queries/futures";
import { FutureBlock } from "./future-block";
import { FutureBatch } from "./future-batch";

export const ExecutionBatches: React.FC<{
ignitionModule: IgnitionModule<string, string, IgnitionModuleResult<string>>;
}> = ({ ignitionModule }) => {
batches: string[][];
}> = ({ ignitionModule, batches }) => {
const futures = useMemo(
() => getAllFuturesForModule(ignitionModule),
[ignitionModule]
Expand All @@ -35,28 +37,40 @@ export const ExecutionBatches: React.FC<{
setToggledInternal(newState);
};

const [currentlyHovered, setCurrentlyHovered] = useState("");

const futureBatches = batches.reduce((acc, batch) => {
const fullBatch = batch.map((id) => futures.find((f) => f.id === id));

return [...acc, fullBatch as Future[]];
}, [] as Future[][]);

return (
<div>
<SectionHeader>
Execution batches <BatchesTooltip />
</SectionHeader>

{/* todo: integrate for placeholder below after batching work */}
<SectionSubHeader>
<strong>8 futures</strong> will be executed across 3{" "}
<strong>batches</strong>
<strong>{futures.length} futures</strong> will be executed across{" "}
{batches.length} <strong>batches</strong>
</SectionSubHeader>

<Actions>
{futures.map((future) => (
<FutureBlock
key={future.id}
future={future}
toggleState={toggleState}
setToggled={setToggled}
/>
))}
</Actions>
<RootModuleBackground>
<RootModuleName>[{ignitionModule.id}]</RootModuleName>
<Actions currentlyHovered={currentlyHovered}>
{futureBatches.map((batch, i) => (
<FutureBatch
key={`batch-${i}`}
batch={batch}
index={i + 1}
toggleState={toggleState}
setToggled={setToggled}
setCurrentlyHovered={setCurrentlyHovered}
/>
))}
</Actions>
</RootModuleBackground>
</div>
);
};
Expand All @@ -80,6 +94,17 @@ const BatchesTooltip: React.FC = () => (
</span>
);

const RootModuleName = styled.div`
font-weight: 700;
padding-bottom: 1.5rem;
`;

const RootModuleBackground = styled.div`
background: #f6f6f6;
border: 1px solid #bebebe;
padding: 1.5rem;
`;

const SectionHeader = styled.div`
font-size: 1.5rem;
margin-bottom: 1rem;
Expand All @@ -91,7 +116,15 @@ const SectionSubHeader = styled.div`
margin-top: 1rem;
`;

const Actions = styled.div`
const Actions = styled.div<{ currentlyHovered: string }>`
display: grid;
row-gap: 0.5rem;
${({ currentlyHovered }) =>
currentlyHovered &&
`
.${currentlyHovered} {
font-weight: 700;
}
`}
`;
Loading

0 comments on commit 6e2ea28

Please sign in to comment.