Add React components for showing model alert results (#3495)
This commit is contained in:
@@ -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[];
|
||||
}
|
||||
@@ -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()],
|
||||
},
|
||||
};
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
52
extensions/ql-vscode/src/view/model-alerts/ModelDetails.tsx
Normal file
52
extensions/ql-vscode/src/view/model-alerts/ModelDetails.tsx
Normal 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>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user