Add React components for showing model alert results (#3495)

This commit is contained in:
Charis Kyriakou
2024-03-20 15:00:33 +00:00
committed by GitHub
parent a8a63a4633
commit 175907d39c
4 changed files with 172 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
import type { AnalysisAlert } from "../../variant-analysis/shared/analysis-result";
import type { ModeledMethod } from "../modeled-method";
export interface ModelAlerts {
model: ModeledMethod;
alerts: AnalysisAlert[];
}

View File

@@ -0,0 +1,22 @@
import type { Meta, StoryFn } from "@storybook/react";
import { ModelAlertsResults as ModelAlertsResultsComponent } from "../../view/model-alerts/ModelAlertsResults";
import { createSinkModeledMethod } from "../../../test/factories/model-editor/modeled-method-factories";
import { createMockAnalysisAlert } from "../../../test/factories/variant-analysis/shared/analysis-alert";
export default {
title: "Model Alerts/Model Alerts Results",
component: ModelAlertsResultsComponent,
} as Meta<typeof ModelAlertsResultsComponent>;
const Template: StoryFn<typeof ModelAlertsResultsComponent> = (args) => (
<ModelAlertsResultsComponent {...args} />
);
export const ModelAlertsResults = Template.bind({});
ModelAlertsResults.args = {
modelAlerts: {
model: createSinkModeledMethod(),
alerts: [createMockAnalysisAlert()],
},
};

View File

@@ -0,0 +1,91 @@
import { styled } from "styled-components";
import type { ModelAlerts } from "../../model-editor/model-alerts/model-alerts";
import { Codicon } from "../common";
import { useState } from "react";
import { VSCodeBadge } from "@vscode/webview-ui-toolkit/react";
import { formatDecimal } from "../../common/number";
import AnalysisAlertResult from "../variant-analysis/AnalysisAlertResult";
import { MethodName } from "../model-editor/MethodName";
import { ModelDetails } from "./ModelDetails";
// This will ensure that these icons have a className which we can use in the TitleContainer
const ExpandCollapseCodicon = styled(Codicon)``;
const TitleContainer = styled.button`
display: flex;
gap: 0.5em;
align-items: center;
width: 100%;
color: var(--vscode-editor-foreground);
background-color: transparent;
border: none;
cursor: pointer;
&:disabled {
cursor: default;
${ExpandCollapseCodicon} {
color: var(--vscode-disabledForeground);
}
}
`;
const ModelTypeText = styled.span`
font-size: 0.85em;
color: var(--vscode-descriptionForeground);
`;
const ModelDetailsContainer = styled.div`
padding-top: 10px;
`;
const AlertsContainer = styled.ul`
list-style-type: none;
margin: 1em 0 0;
padding: 0.5em 0 0 0;
`;
const Alert = styled.li`
margin-bottom: 1em;
background-color: var(--vscode-notifications-background);
`;
interface Props {
modelAlerts: ModelAlerts;
}
export const ModelAlertsResults = ({
modelAlerts,
}: Props): React.JSX.Element => {
const [isExpanded, setExpanded] = useState(true);
return (
<div>
<TitleContainer onClick={() => setExpanded(!isExpanded)}>
{isExpanded && (
<ExpandCollapseCodicon name="chevron-down" label="Collapse" />
)}
{!isExpanded && (
<ExpandCollapseCodicon name="chevron-right" label="Expand" />
)}
<VSCodeBadge>{formatDecimal(modelAlerts.alerts.length)}</VSCodeBadge>
<MethodName {...modelAlerts.model}></MethodName>
<ModelTypeText>{modelAlerts.model.type}</ModelTypeText>
</TitleContainer>
{isExpanded && (
<>
<ModelDetailsContainer>
<ModelDetails model={modelAlerts.model} />
</ModelDetailsContainer>
<AlertsContainer>
{modelAlerts.alerts.map((r, i) => (
<Alert key={i}>
<AnalysisAlertResult alert={r} />
</Alert>
))}
</AlertsContainer>
</>
)}
</div>
);
};

View File

@@ -0,0 +1,52 @@
import { styled } from "styled-components";
import {
modeledMethodSupportsInput,
modeledMethodSupportsKind,
modeledMethodSupportsOutput,
} from "../../model-editor/modeled-method";
import type { ModeledMethod } from "../../model-editor/modeled-method";
const DetailsContainer = styled.div`
display: flex;
`;
const Detail = styled.span`
display: flex;
margin-right: 30px;
`;
const Label = styled.span`
color: var(--vscode-descriptionForeground);
margin-right: 10px;
`;
const Value = styled.span``;
export const ModelDetails = ({ model }: { model: ModeledMethod }) => {
return (
<DetailsContainer>
<Detail>
<Label>Model type:</Label>
<Value>{model.type}</Value>
</Detail>
{modeledMethodSupportsInput(model) && (
<Detail>
<Label>Input:</Label>
<Value>{model.input}</Value>
</Detail>
)}
{modeledMethodSupportsOutput(model) && (
<Detail>
<Label>Output:</Label>
<Value>{model.output}</Value>
</Detail>
)}
{modeledMethodSupportsKind(model) && (
<Detail>
<Label>Kind:</Label>
<Value>{model.kind}</Value>
</Detail>
)}
</DetailsContainer>
);
};